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

动态枚举来自数据库表

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.82/5 (10投票s)

2008年11月14日

CPOL

3分钟阅读

viewsIcon

54585

创建一个包含在数据库中定义的枚举的程序集。

引言

通过使用本文中提供的代码,您的应用程序可以轻松生成动态枚举。

背景

数据库应用程序编程的一个重要部分是识别和使用查找项,这些查找项在功能上类似于常量。在 .NET 之前,开发人员可以在数据库表中定义查找值,但为了在应用程序中将它们用作常量,他们需要一个单独的步骤,以 CONST 值或枚举的形式在应用程序中定义它们。这有时会带来问题 - 如何确保数据库值与应用程序值保持同步。使用 EnumBuilder 类和应用程序中的几行代码,所有这些都可以在您无需任何干预的情况下实现。

Using the Code

首先,在您的代码中设置对 System.Reflection.Emit 的引用。

Imports System.Reflection.Emit

下面的代码非常简单易用。只需在代码开始时将一些变量设置为您的值即可。此代码将创建一个新的程序集,由 assemblyName 变量指定,带有 DLL 扩展名,位于应用程序文件夹中。

OpenDatabase() 'you provide this
Try
    Dim assemblyName As String = "DynEnum"
    Dim lookupSQL As String = "SELECT ID, Name FROM AllMessageTypes"
    Dim nameField As String = "Name"
    Dim valueField As String = "ID"
    Dim enumerationName As String = "MessageTypes"

    Dim currentDomain As AppDomain = AppDomain.CurrentDomain
    Dim aName As AssemblyName = New AssemblyName(assemblyName)
    Dim ab As AssemblyBuilder = _
        currentDomain.DefineDynamicAssembly(aName, _
        AssemblyBuilderAccess.RunAndSave)
    Dim mb As ModuleBuilder = ab.DefineDynamicModule(aName.Name, _
                              aName.Name & ".dll")

    Dim eb As EnumBuilder = mb.DefineEnum(enumerationName, _
              TypeAttributes.Public, GetType(Integer))

    'your saved connection
    Dim cmd As New SqlCommand(lookupSQL, _Connection)
    Dim dr As SqlDataReader = cmd.ExecuteReader
    If dr.HasRows Then
        Do While dr.Read
            eb.DefineLiteral(dr.GetValue(dr.GetOrdinal(nameField)), _
                             dr.GetValue(dr.GetOrdinal(valueField)))
        Loop
    End If
    dr.Close()
    eb.CreateType()

    ab.Save(aName.Name & ".dll")
Catch ex As Exception
    Throw ex
End Try

从这一点开始,您只需在运行一次应用程序并创建生成的 DLL 后,将 DLL 添加到应用程序的引用即可。如果您在查找表中添加或删除任何值,它会自动反映在枚举中,因为它是由应用程序生成的。

我将此代码放在将使用枚举的类的构造函数中,尽管我不认为它与应用程序的其余部分相关。如果您发现情况并非如此,请告诉我。

此方法可能存在的问题

我尚未验证这一点,但在应用程序执行期间,防病毒应用程序可能会将 DLL 中的更改视为受感染的文件,因此您可能需要注意这种情况。

关注点

有趣的是,即使您在应用程序中引用了新创建的 DLL,当应用程序运行并重新生成 DLL 时,也不会引发文件正在使用异常。我本以为会是这种情况,但它直接通过代码并创建新的 DLL。如果有人能向我解释这一点,我将不胜感激。此外,如果您在表中放置一个新值并运行您的应用程序,则新值会立即提供给应用程序。当然,在您停止应用程序之前,新值对 Visual Studio 的智能感知不可用。

更新:我想我已经确定了为什么在重新生成 DLL 时没有收到文件正在使用错误。据我了解,.NET DLL 实际上直到使用时才加载。在这种情况下,只要在重新生成之前没有使用过我们的动态 DLL,它就会被重新生成。因此,如果在重新生成代码之前,应用程序中的任何其他类都没有使用正在生成的枚举,我们的 DLL 将使用插入表中的任何新值重新生成。但不幸的是,这也意味着我们不能在发生重新生成的类中拥有我们枚举类型的 PrivateFriendProtectedPublic 变量,因为这些变量是在运行类构造函数代码之前初始化的。所以请注意您正在创建的枚举变量的作用域,否则您将收到文件正在使用异常。

历史

  • 原始提交 - 2008 年 11 月 14 日,星期五
  • 更新 - 2008 年 11 月 19 日,星期三
© . All rights reserved.