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

dbObject - 使用属性进行数据库代码生成

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.95/5 (6投票s)

2006年1月26日

4分钟阅读

viewsIcon

55442

downloadIcon

434

一个简易的 OR 工具,用于根据 MySQL 数据库生成 VB.NET 数据库代码。

Sample screenshot

引言

这是一个我编写的示例框架。它的工作方式基本上类似于一个简易的 OR 工具,从数据库表生成 VB.NET 代码,并使用属性来控制更新和插入。

在设计系统时,我通常喜欢从数据库设计开始。使用数据模型可以帮助我想象系统将由哪些对象组成。在“对象挖掘”过程中,关于新系统最容易收集的信息是将被推送的数据。

使用 Microsoft 的 Recordset 是一种将表抽象为对象的绝佳方法。我遇到的问题是,当我尝试将 Recordset 与 MySQL 一起使用时,许多漂亮的钣金都脱落了。我开始编写自己的访问层,但发现自己一遍又一遍地重写相同的基本代码。显然,需要一个代码生成器。

因此,通过这种方法,我从表布局生成代码,每个字段都变成一个属性。通过检查数据库表的架构,我可以将属性应用于生成的 VB.NET 代码,并构造辅助函数来选择和更新底层数据。

背景

有很多关于基于属性的编程的优秀文章,其中一些就在 Code Project 上。MySQL 信息可以在这里找到。

使用代码

这里提供的代码是我在几个项目中使用的代码的摘录。此外,我编写了一个 Visual Studio .NET 插件,可以生成代码并将代码添加到我正在处理的项目中。

要使用此代码,您需要在您的机器上安装、配置和运行 MySQL。您还应该安装 MySQL 的 ODBC 连接器。涵盖这些方面超出了本文的范围。

您需要创建一个名为“dbObject”的数据库。您应该创建一个指向“dbObject”表的 ODBC 数据源,并测试连接。

在“dbObject”数据库中创建一个测试表。

DROP TABLE IF EXISTS `dbobject`.`protocols`;
CREATE TABLE  `dbobject`.`protocols` (
  `ProtocolType` varchar(20) NOT NULL default '',
  `Enabled` varchar(1) NOT NULL default '',
  `RootLocation` varchar(255) NOT NULL default '',
  PRIMARY KEY  (`ProtocolType`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 
  COMMENT='Sample table to hold communication protocol descriptions.';

运行该程序会显示一个简单的 Windows 窗体,允许选择数据库和表。

  1. 按“连接”按钮,使用文本框中显示的连接字符串连接到 MySQL 数据库。
  2. 选择一个数据库,然后选择一个表。
  3. 单击“选择”按钮,从所选表的架构生成 VB.NET 代码。

生成 VB.NET 类的实际代码非常简单

' Instance a code generator and set the various props
Dim oGeneratorSQL As New cGenerate_SQL
oGeneratorSQL.ConnectionString = oSelectTable.ConnectionString
oGeneratorSQL.DatabaseName = oSelectTable.DatabaseName
oGeneratorSQL.TableName = oSelectTable.TableName
oGeneratorSQL.UseDBFramework = True
oGeneratorSQL.InsertFrameworkIfMissing = False
' Instance a form to display the generated code
Dim oCodeViewer As New frmViewCode
' Generate the code and show the form
oCodeViewer.RichTextBox1.Text = oGeneratorSQL.GenerateInsertCode()
oCodeViewer.ShowDialog()

示例程序打开一个带有富文本框控件的窗体。生成的 VB.NET 代码设置为富文本框的 Text 属性。在我的 Visual Studio 插件中,我使用 Environment DTE 将生成的代码插入到当前光标位置。

Select Table Dialog

关注点

因为我打算将代码生成用于 Visual Studio 插件的各种功能,所以我设计了对象的生成以共享一个通用接口,以便以后可以扩展该功能。

其中一个类,cGenerateProperty 对象,我经常在另一个 Visual Studio 插件中使用,该插件生成成员变量和属性访问器方法。右键单击“插入属性”并键入“CustomerName”,然后让该插件生成所有需要的代码,这样会容易得多。

Insert a new property

Code Generation Relationships

dbObject_Framework

大多数操作发生在 dbObject_Framework 中。当代码生成器创建一个对象时,它会从框架中的 cBase_DBObj 类继承它。

Public Class cJobs Inherits cBase_DBObj
End Class

dbObject_Framework 处理大部分繁重的工作。我使用反射来获取关于给定类的各种信息,然后基于这些信息生成 SQL 命令来插入、更新等。

' Instantiate a new object of the passed in ClassName
Dim vbObj As Object = oThis.CreateInstance(sClassName, False, _
          BindingFlags.Default, Nothing, Nothing, Nothing, Nothing)

' Get the Type object for this class,
' and from the type, get the properties
Dim vbClassType As Type = oThis.GetType(sClassName)
Dim oProps() As Reflection.PropertyInfo = Me.GetType.GetProperties()

For Each oProp As Reflection.PropertyInfo In oProps
    Dim sPropName As String = oProp.Name
    Dim sIsSerializable As String = _
        oDriver.GetPropertyAttribute(oThis, _
        sClassNameShort, sPropName, _
        "IsSerializable").ToUpper
    ' Only attempt the read the property
    ' from the database if the property 
    ' is marked "Serializable" via an attribute
    If sIsSerializable = "TRUE" Then
        ' Get the type code of the data from the database
        Dim oDBType As TypeCode = _
          Type.GetTypeCode(oRS(sPropName).GetType)
        ' Get the type code of the property on the object
        Dim oPropType As TypeCode = _
          Type.GetTypeCode(oProp.PropertyType)
        
        ' Convert the data
        If oDBType <> oPropType Then
            ' Convert the database data type
            ' into the object's property data type
            ' Note: In a future version that generates
            ' custom property types from the database, 
            ' this marshalling step will not have
            ' to happen, since the types should agree...
            Select Case Type.GetTypeCode(oProp.PropertyType)
                Case TypeCode.String
                    oProp.SetValue(vbObj, _
                       oRS(sPropName).ToString, Nothing)
                    Case TypeCode.Boolean
                    Dim iTemp As Integer = oRS(sPropName)
                    If iTemp = 0 Then
                        oProp.SetValue(vbObj, False, Nothing)
                    Else
                        oProp.SetValue(vbObj, True, Nothing)
                    End If
                Case Else
                    ' Treat it like a string 
                    oProp.SetValue(vbObj, oRS(sPropName), Nothing)
            End Select
        Else ' They match, so straight convert 
            ' Set the property values from the database 
            oProp.SetValue(vbObj, oRS(sPropName), Nothing)
        End If
    End If
Next

使用此工具生成的类只是创建对象并调用 GetSelectedRecords 函数的问题。GetSelectedRecords 函数是从 dbObject_Framework 继承的。它返回一个符合条件的对象的 ArrayList

ArrayList = Object.GetSelectedRecords( criteria, connectionString)

在下面的示例代码中,我们实例化一个新的 cMerchants 对象,并调用它的 GetSelectedRecords() 方法。您可以通过 SQL WHERE 子句的形式传递一个可选的过滤器语句。

GetSelectedRecords() 函数检查类结构,生成正确的 SQL 查询,针对数据库运行查询,并将结果作为 cMerchants 对象的 ArrayList 返回。

Dim oDown As New cMerchants
Dim sConn As String = _
    ConfigurationSettings.AppSettings("DBConnKey")

Dim sSQL As String = "WHERE MerchantID = '" _
                     & sMerchantID & "'"

Dim oArrayMerchants As New ArrayList
oArrayMerchants = oDown.GetSelectedRecords(sSQL, sConn)

If oArrayMerchants.Count > 0 Then
    ' Do Something
End If

历史

  • 2006-01-26 - 首次提交到 Code Project。
© . All rights reserved.