【问题标题】:How can I loosely couple database columns in a .NET application?如何在 .NET 应用程序中松散耦合数据库列?
【发布时间】:2009-01-15 01:11:36
【问题描述】:

我有两个版本几乎相同的数据库。下面我创建了一个示例表来演示基本区别,即 ID 列已从整数标识更改为 GUID 并更新了各种属性,在示例中存档已替换为只读和隐藏:

旧版:

CREATE TABLE Example
(
    --Data Identity (maps to DbId in the example code)
    Id int IDENTITY PRIMARY KEY,

    --Example columns
    SomeValue varchar(50),
    AnotherValue int,

    --Data Properties
    Archived bit
)

新版本:

CREATE TABLE Example
(
    --Data Identity (maps to DbId in the example code)
    Id uniqueidentifier PRIMARY KEY,

    --Example columns
    SomeValue varchar(50),
    AnotherValue int,

    --Data Properties
    ReadOnly bit,
    Hidden bit
)

我需要能够使用诸如 NHibernate 之类的 O/R 映射器来连接到这些数据库版本中的一个或其他。我希望能够通过配置文件中的设置告诉应用程序使用哪个版本。

我最初的计划是为业务逻辑创建一个通用接口,并使用 Unity 等 IoC 容器在配置文件中的相关具体类之间进行交换。

以下是我为测试该理论而创建的代码示例:

public interface IDataIdentity
{
    object Id { get; }
}

public class LegacyDataIdentity : IDataIdentity
{
    public virtual long DbId { get; set; }

    public object Id
    {
        get { return DbId; }
    }
}

public class NewDataIdentity : IDataIdentity
{
    public virtual Guid DbId { get; set; }

    public object Id
    {
        get { return DbId; }
    }
}


public interface IDataProperties
{
    bool ReadOnly { get; set; }
    bool Hidden { get; set; }
}

public class LegacyDataProperties : IDataProperties
{
    public virtual bool Archived { get; set; }

    public bool ReadOnly
    {
        get { return Archived; }
        set { Archived = value; }
    }

    public bool Hidden
    {
        get { return Archived; }
        set { Archived = value; }
    }
}

public class NewDataProperties : IDataProperties
{
    public virtual bool ReadOnly { get; set; }
    public virtual bool Hidden { get; set; }
}


public class DataItem
{
    public DataItem(IDataIdentity dataIdentity, IDataProperties dataProperties)
    {
        DataIdentity = dataIdentity;
        DataProperties = dataProperties;
    }

    public IDataIdentity DataIdentity { get; set; }
    public IDataProperties DataProperties { get; set; }
}

public class Example : DataItem
{
    public Example(IDataIdentity dataIdentity, IDataProperties dataProperties)
        : base(dataIdentity, dataProperties)
    {
    }

    public virtual string SomeValue { get; set; }
    public virtual int AnotherValue { get; set; }
}

谁能建议这是否可行(特别是使用 Unity 和 NHibernate),如果可以,如何创建相关的 NHibernate 映射文件?

或者,任何人都可以使用任何其他方法或其他 IoC 和 O/R 映射工具(商业或开源)提出任何解决问题的方法吗?

非常感谢,

保罗

【问题讨论】:

    标签: c# .net nhibernate unity-container loose-coupling


    【解决方案1】:

    为什么不抽象您的数据提供者,实现 2 个版本(一个用于旧数据项的休眠映射,一个用于新数据项)。

    稍微解释一下您的代码(为清楚起见进行了简化):

    public abstract class AbstractData
    {
        public abstract string SomeValue { get; set; }
        public abstract bool ReadOnly { get; set; }
        //etc.
    }
    
    public interface IDataProvider
    {
        AbstractData Get(object id);
    }
    
    public class LegacyData : AbstractData
    {
         // Implement AbstractData, and
         public virtual long Id { get { return m_Id; } set { m_Id = value; };
         private long m_Id;
    }
    
    public class LegacyDataNHibernateProvider : IDataProvider
    {
         public LegacyDataProvider()
         {
             // Set up fluent nhibernate mapping 
         }
    
         public AbstractData Get(object id)
         {
               // Interpret id as legacy identifier, retrieve LegacyData item, and return
         }
    };
    
    // Same again for new data provider
    

    这样,您就不会被绑定到 nhibernate(或数据库,就此而言),并且您可以指定具有正确类型标识符的具体类(nhibernate 可以处理)。这是我正在采用的方法,我目前必须针对现有数据库的 SP 进行映射,但稍后将迁移到基于 ORM 的新系统。

    【讨论】:

      【解决方案2】:

      也许我没有正确理解您的问题,但在我看来您需要实现类似“工厂模式”之类的东西。

      当我工作的公司从 JDE 切换到 SAP 时,我最近使用工厂模式将 (c#) 编码到两个数据层。我能够翻转配置开关以在两个数据层之间切换,而 GUI 不会有任何不同。

      这是我找到的几个链接:

      http://msdn.microsoft.com/en-us/library/ms954600.aspx http://www.allapplabs.com/java_design_patterns/factory_pattern.htm http://en.wikipedia.org/wiki/Abstract_factory_pattern

      就 NHibernate 而言,我不熟悉它......对不起。希望这会有所帮助。

      【讨论】:

        【解决方案3】:

        在不了解全貌的情况下很难推荐,但是....您可以通过让 SP 为两个表结构返回相同的数据集来在 SP 中创建一个抽象。

        我想到的另一个抽象是,您实际上可以指定不同的 hybernate 映射文件,并根据您连接到的数据库使用不同的文件初始化 Hibernate。

        【讨论】:

          猜你喜欢
          • 2010-11-28
          • 2012-02-27
          • 1970-01-01
          • 2016-05-24
          • 2013-07-29
          • 2020-10-26
          • 1970-01-01
          • 2017-06-05
          • 2012-02-18
          相关资源
          最近更新 更多