2

我有一个几乎相同的数据库的两个版本。下面我创建了一个示例表来演示基本差异,即 ID 列已从 Integer Identity 更改为 GUID 并更新了各种属性,在示例中存档已替换为 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 映射工具(商业或开源)提出任何解决问题的方法吗?

非常感谢,

保罗

4

3 回答 3

2

为什么不抽象您的数据提供者,实现 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 的系统。

于 2009-01-20T11:35:10.650 回答
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 而言,我不熟悉它......对不起。希望这可以帮助。

于 2009-01-15T04:40:23.577 回答
0

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

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

于 2009-01-15T05:02:08.180 回答