65.9K
CodeProject 正在变化。 阅读更多。
Home

用于在 HTML 中生成数据库设计文档的 Web 控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.59/5 (10投票s)

2006年1月24日

MIT

2分钟阅读

viewsIcon

87454

downloadIcon

1838

仅用200行VB.NET代码来记录你的SQL Server数据库。

引言

这段代码是一个服务器控件,用于在Web上发布你的数据库结构(表、列、视图、触发器和存储过程)。它是用VB.NET编写的,但可以很容易地用任何其他语言编写。 该控件可以嵌套在任何ASPX页面中,以提供一个格式良好的数据库设计文档,该文档始终是最新的并可在线访问。

DBreporter screenshot

背景

SQL Server将其所有数据库对象定义存储在其系统表中;因此,像查询任何其他数据库表一样查询它是很容易的。在我的示例中,相关的字典表是

  • sysobjects(包含表、视图、存储过程和触发器的名称)。
  • syscolumns(包含列和存储过程参数名称)。
  • systypes(包含在企业管理器中显示的列类型)。
  • syscomments(包含视图、存储过程和触发器的SQL脚本)。

SQL Server字典的部分图表

SQL Server dictionary

另一个执行相同操作的Web控件(用C#和XSLT代替VB.NET)由Jose A. Gonzalvo发布。因为我使用不同的算法,并且我还记录了存储过程和触发器SQL脚本,所以我将我的代码提供给社区。

使用代码

这个Web控件必须像任何其他Web控件一样嵌套在ASPX页面中。它有一个名为SqlConnection的属性,用于指定数据库连接字符串。 必须授予用户对系统表的读取权限。

随附的示例项目包含一个样式表(具有类RowHeaderRowOddRowEvenSQL)以及一些图片,使其看起来很漂亮。 不要忘记将它们包含在你的项目中。

代码

我的代码分为三个部分

  • 查询字典
  • 将数据集组织成层次结构
  • 渲染HTML

可以用不同的方式查询字典。 使用SQL Server 2000,我编写了以下SQL

'### Objects (Tables, Views, Stored Procedures, Triggers) ###

sql = "SELECT id, name, rtrim(xtype) as xtype " & _
      "FROM sysobjects SO " & _
      "WHERE SO.status>-1 AND SO.xtype in ('U','V','P','TR') " & _
      "ORDER BY name;"

'### Columns or Parameters ###

sql &= "SELECT SC.id, SC.name, SC.isnullable, ST.name AS typename, " & _
       "CASE WHEN SC.xtype = 231 THEN SC.length/2" & _ 
       " ELSE SC.length END AS length " & _
       "FROM systypes ST, syscolumns SC, sysobjects SO " & _
       "WHERE SC.xtype=ST.xtype " & _
         " AND SC.id=SO.id" & _
         " AND SO.status>-1 AND SO.xtype in ('U','V','P') " & _
         " AND ST.length<>256 " & _
       "ORDER BY SO.name, SC.colid;"

'### SQL Scripts ###

sql &= "SELECT SC.id, SC.text AS sql " & _
       "FROM syscomments SC, sysobjects SO " & _
       "WHERE SO.id=SC.id" & _
         " AND SO.status>-1 AND SO.xtype in ('TR','V','P'); "

为了更有效地处理数据,我一次提交我的三个查询,并将结果检索到单个DataSet中。

将层次结构构建并将DataSet转换为XML的方法如下

ds.DataSetName = "dbreport"
ds.Tables(0).TableName = "entity"
ds.Tables(1).TableName = "column"
ds.Tables(2).TableName = "definition"
MaxLoop = ds.Tables.Count - 1
For i = 0 To MaxLoop
    With ds.Tables(i)
        For j = 0 To .Columns.Count - 1
            .Columns(j).ColumnName = LCase(.Columns(j).ColumnName)
            .Columns(j).ColumnMapping = MappingType.Attribute
        Next
        .Columns("id").ColumnMapping = MappingType.Hidden
    End With
Next
With ds
    Dim rel1 As DataRelation = .Relations.Add("entity-column", _
        ds.Tables("entity").Columns("id"), _
        ds.Tables("column").Columns("id"))
    rel1.Nested = True
    Dim rel2 As DataRelation = .Relations.Add("entity-definition", _
        ds.Tables("entity").Columns("id"), _
        ds.Tables("definition").Columns("id"))
    rel2.Nested = True
End With
myDOM.LoadXml(ds.GetXml)

生成的XML将如下所示

<dbreport>
  <entity name="Alphabetical list of products" xtype="V">
    <column name="ProductID" isnullable="0" 
               typename="int" length="4" />
    <column name="ProductName" isnullable="0" 
               typename="nvarchar" length="40" />
    <column name="SupplierID" isnullable="1" 
               typename="int" length="4" />
    <column name="CategoryID" isnullable="1" 
               typename="int" length="4" />
     ...
    <definition sql="create view "Alphabetical list of products" 
            AS SELECT Products.*, 
            Categories.CategoryName FROM Categories 
            INNER JOIN Products ON Categories.CategoryID = 
            Products.CategoryID 
            WHERE (((Products.Discontinued)=0))" />
   </entity>
   ...
</dbreport>

从这个XML文档中,现在很容易生成HTML。我使用System.Text.StringBuilder来执行此操作,使用我的XML文档的元素和属性来连接HTML标记的字符串。 这种最后的转换也可以使用XSLT来完成。

注释

为了获取列长度,我使用以下SQL代替查询syscolumns.length

CASE WHEN SC.xtype = 231 THEN SC.length/2 ELSE SC.length END AS length

为了与Enterprise manager保持一致,后者显示 nvarchar 作为字符串长度,而不是存储它所需的空间。

有关更多信息,请访问MSDN网站,其中提供了SQL Server系统表的详细说明。

© . All rights reserved.