设计类以应对频繁的数据库模式更改

时间:2012-11-14 03:45:40

标签: c# class-design

我正在处理由另一个系统维护的数据库,因此我无法对表进行任何重大更改。此数据库中的表具有相当多的字段(超过30+),没有两个表具有相同的命名约定,类型或相同数量的字段。这些表也经常更改(添加,删除字段或更改其类型),更糟糕的是,新表也会频繁创建。现在我有一个可以严格键入的表,用作队列。

问题:

我必须从表中获取表名和表中的一些列。列名称以字符串形式提供。由于这些表经常更改,因此很难为每个表维护严格类型的实体。

我如何以松散耦合的方式设计我的类,但允许我使用这些表?

如果我的解释很糟糕,感谢您的帮助和抱歉。

3 个答案:

答案 0 :(得分:1)

我不确定您可以从不稳定的数据中获得什么样的业务逻辑。我的假设是你正在对与记录相关的元数据做一些工作。使用数据的聚合(计数,平均值等)而不是实际数据。

我会使用DataSet,使用类似的通用SQL语句:

SELECT * FROM {dynamic table name}

答案 1 :(得分:1)

一个想法是使用SQL Management Objects (SMO)Tables来动态创建强类型。

Server srv = new Server(conn);
Database db = srv.Databases["AdventureWorks"];

foreach (Table table in db.Tables)
{
    Console.WriteLine(" " + table.Name);
    foreach (Column col in table.Columns)
    {
        Console.WriteLine("  " + col.Name + " " + col.DataType.Name);
    }
}

我已经用这种方式编写了数据访问层的单元测试生成器,你可以使用列DataTypes编写类,例如(在线查看更好的实现 - 在C#中):

Public Function SQLParameterType(ByVal ParameterDataType As String) As String

    ParameterDataType = ParameterDataType.ToUpper

    If ParameterDataType.IndexOf("NVARCHAR") > 0 Then
        Return "string"
    ElseIf ParameterDataType.IndexOf("VARCHAR") > 0 Then
        Return "string"
    End If

    Select Case ParameterDataType

        Case Is = "BIGINT"
            Return "Int64"
        Case Is = "INT"
            Return "Int32"
        Case Is = "SMALLINT"
            Return "Int16"

        Case Is = "BIT"
            If gIsVBdotNet Then
                Return "boolean"
            Else
                Return "bool"
            End If

        Case Is = "DATETIME"
            Return "DateTime"

        Case Is = "DATETIME2"
            Return "DateTime"

        Case Is = "SMALLDATETIME"
            Return "DateTime"

        Case Is = "MONEY"
            Return "single" 'float
        Case Is = "FLOAT"
            Return "single" 'float
        Case Is = "REAL"
            Return "double"
            'Case Is = "INT"
            '    Return "int32"
            'Case Is = "INT"
            '    Return "int32"
        Case Else
            Return "666"
    End Select

End Function

使用这种以模式中立方式连接到数据库的简单ORM,您可以将动态生成的类松散地耦合到dB。 .Net 4中的新Dynamic类型似乎是此应用程序的一个很好的多态数据类型。

答案 2 :(得分:0)

快速修复(不是解决方案)是使用代码生成实用程序like this one,它将根据您的模板或数据库模式定义本身更新/创建类文件。通过一些工作,这可以通过custom MsBuild task在您的项目中完全自动化,这将在您构建项目时运行。您的文件将直接更新到您的解决方案文件夹中。

但最重要的是,当您的表定义更新时,它会在构建时破坏您的代码 - 显示由于表定义更改而必须修复的位置。为此,您的自定义MsBuild任务必须在主构建任务之前运行explained here

这肯定会让你感到受益并让事情变得简单,因为我已经看到这样的设计有益于一个类似的项目,但最终“废话 - 废话”原则仍将占上风,所以上述'修复'只会对待症状不是原因,可能是设计不佳,缺乏对解决方案数据需求的抽象和分析。因此,你得到一个需要重新编程的程序才能重新配置:)但对于LOB编程,这并不罕见:)

**注意:如果您决定使用第一段中描述的设计,为了获得完整的解决方案,您可能需要额外的MsBuild任务,该任务会自动检出需要从您的源更新的文件控制架构何时更改。如果您需要更多信息,请发表评论。

总结:当您按F5在Visual Studio中构建解决方案时,将会发生的所有类将使用数据库中的最新定义进行神奇更新。您还可以将此约束仅限于Release版本,这样您在开发时每次构建Debug模式时都无法完成此操作。