如何在.NET应用程序中松散地耦合数据库列?

时间:2009-01-15 01:11:37

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

我有几个完全相同的数据库的两个版本。下面我创建了一个Example表来演示基本的差异,即ID列已从Integer Identity更改为GUID并且各种属性已更新,在示例archived中已替换为readOnly并隐藏:

传统版本:

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映射工具(商业或开源)建议任何解决问题的方法吗?

非常感谢,

3 个答案:

答案 0 :(得分:2)

为什么不抽象数据提供程序,实现2个版本(一个版本具有旧数据项的nhibernate映射,另一个版本适用于新数据项)。

稍微解释一下你的代码(为简洁起见,简化了):

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的系统。

答案 1 :(得分:0)

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

当我工作的公司从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而言,我对它并不熟悉...抱歉。希望这会有所帮助。

答案 2 :(得分:0)

很难在不知道完整图片的情况下推荐,但是......你可以通过让SP为两个表结构返回相同的数据集来在SP中创建一个abstruction。

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