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

版本化数据库访问

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.40/5 (2投票s)

2007 年 7 月 19 日

5分钟阅读

viewsIcon

23422

downloadIcon

358

使用正确的数据访问类来适应当前版本的数据库。

Screenshot - ScreenShot.jpg

引言

此代码提供了指定类可以访问哪个数据库版本的能力。它使用抽象工厂 [Gamma et al, 1995, p87] 模式,根据从数据库检索到的版本信息和分配给每个类的自定义属性来创建数据访问对象。

背景

每当我创建一个数据库时,我做的第一件事就是编写一个返回版本信息的存储过程。这样,随着数据库的变化,我可以更新存储过程中的主版本、次版本或修订号来反映更改的类型。

CREATE PROCEDURE dbo.uspVersion(@systemName SYSNAME = NULL OUTPUT, 
    @major INT = NULL OUTPUT,
    @minor INT = NULL OUTPUT, 
    @revision INT = NULL OUTPUT, 
    @showOutput BIT = 1) AS
BEGIN
    SET NOCOUNT ON

    SELECT @systemName = 'Version Database System',
        @major = 1,
        @minor = 0,
        @revision = 0

    IF @showOutput = 1
    BEGIN
        SELECT @systemName AS [System Name], @major AS Major,
            @minor AS Minor, @revision AS Revision
    END
END

在访问数据库的应用程序中,我在连接后检查数据库版本,以确保系统名称是我们期望的值。然后,我使用版本号来决定使用哪个类来访问数据。这使我能够发布可以使用数据库升级的新软件,但前提是数据库必须是特定版本或更高版本。如果新软件因任何原因失败,我只需回滚软件实现,而无需回滚数据库。一旦我确信新软件运行良好,我就可以执行数据库升级,新软件应该就可以开始使用新功能了。过去,我使用 Delphi 中的硬编码 switch 语句来实现这一点。现在我使用 C#,我认为 .NET 平台强大的类型信息、自定义属性和反射可能提供更灵活的方法。

使用代码

代码的工作原理是将自定义属性 VersionAttribute 分配给数据访问类。当您使用抽象工厂的 MakeXXXX 方法之一创建数据访问对象时,它会返回一个代理对象。代理对象执行数据库连接并检索版本信息。利用这些信息,它会搜索程序集以查找具有 VersionSpecificAttribute 的类,以对应数据库版本。您可以为类指定完整的版本号 Major.Minor.Revision,或者指定它是特定版本的通用类 Major.Minor.AnyRevision

如果搜索算法找不到特定类,它将使用通用类。如果找不到 Major.Minor 版本的通用类,则会抛出异常。这是有意为之的。如果您对数据库进行了需要更新主版本号或次版本号的更改,您至少应检查现有代码以确保其功能。如果不需要更改,只需为该版本添加通用的 VersionSpecificAttribute 并重新构建即可。

Versioned.Data 项目提供了创建版本化数据访问层的类,而演示项目 Rainbow.DataRainbow.Data.Sql 是 Rainbow 数据库的数据访问层。VidbTest 项目是一个简单的 Windows Forms 测试应用程序,用于从虚构的 Rainbow 系统检索产品信息。

版本化数据访问库:Versioned.Data

Versioned.Data 项目提供了创建版本化数据访问层的所有基本功能。第一步是创建特定于您的系统的版本化连接对象。派生自 VersionedDbConnection 类并重写 ConnectToDatabaseRetrieveDatabaseVersion 方法。DefaultVersion 实用类提供使用上面创建的存储过程检索数据库版本的方法。如果您使用其他方法,您需要提供正确的实现。

其次,创建一个派生自 TableProxy 的数据访问表类,并指定实现的类型,通常是数据表接口。这是您想要访问数据库时创建的对象。最后,创建派生自 DataTable 类并且应用了 VersionSpecificAttribute 的版本特定数据访问表。该类的实例执行数据库特定版本的实际数据访问。

就是这样。我建议您的基类是版本通用的数据表,而特定类则派生自它并重写功能已更改的方法。当主版本或次版本更改时,我建议创建一个全新的类,因为主版本或次版本的更改通常会破坏功能而不是扩展它。

演示项目布局

关于演示项目,我只想快速说一句:我倾向于以相同的方式布局所有数据访问层。这样我就可以轻松使用版本化数据访问库。我有一个抽象数据层,其中包含一个创建数据访问表的抽象工厂对象。然后,我为特定数据库或技术的(例如 ADO.NET)数据访问层创建一个实现项目。

这些分离使我能够轻松地将数据访问层从,例如,Microsoft SQL Server 更改为 Oracle,只需实现一个新的具体数据访问工厂。我计划发布另一篇文章,介绍如何在运行时动态更改具体数据访问工厂的代码,敬请关注。尽管这些分离对于使用版本化数据访问代码并非严格必需,但我强烈建议使用它们,因为我认为该设计符合 OCP(开放封闭原则 [Martin, 2003, p99])。

要使用演示项目,您需要创建 Rainbow 数据库。它是一个 SQL Server 数据库,脚本在演示解决方案的 SqlServer.Scripts 文件夹中提供。我还提供了用于升级或降级到各种数据库版本的脚本。我建议您创建数据库并进行升级/降级,同时运行测试应用程序来检查结果。

参考文献

  • Gamma, Erich and Helm, Richard and Johnson, Ralph and Vlissides John, Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley, Indianapolis, 1995
  • Martin, Robert C, Agile Software Development: Principles, Patterns and Practices, Prentice Hall, New Jersey, 2003

历史

  • 2007/07/18 - 初始版本
  • 2007/07/20 - 添加了参考文献
© . All rights reserved.