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

发布于 2024-07-12 11:51:36 字数 2537 浏览 10 评论 0原文

我有两个版本的几乎相同的数据库。 下面我创建了一个示例表来演示基本差异,即 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
)

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

我最初的计划是为业务逻辑创建一个通用接口,并使用 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 映射工具(商业或开源)来解决该问题吗?

非常感谢,

保罗

I have two versions of an almost identical database. Below I have created an Example table to demonstrate the basic differences, namely the ID column has changed from an Integer Identity to a GUID and various properties have been updated, in the Example archived has been replaced with readOnly and hidden:

Legacy version:

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
)

New version:

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
)

I need to be able to use an O/R mapper such as NHibernate to connect to one or other of these database versions. I would like to be able to tell the application which version to use through settings in a configuration file.

My initial plan was to create a common interface for the business logic and use an IoC container such as Unity to swap between the relevant concrete classes in the configuration file.

Below is an example of the code I created to test this theory:

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; }
}

Can anyone advise if this is possible (specifically with Unity and NHibernate) and if so how to create the relevant NHibernate mapping files?

Alternatively, can anyone suggest any solution to the problem using any other methods or other IoC and O/R mapping tools (commercial or open source)?

Many thanks,

Paul

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不再让梦枯萎 2024-07-19 11:51:37

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

Why not abstract your data provider, implementing 2 versions (one with nhibernate mappings for the legacy data item, and one for the new data item).

To paraphrase your code slightly (simplified for clarity):

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

This way, you aren't tied to nhibernate (or a database, for that matter), and you can specify concrete classes with correctly typed identifiers (which nhibernate can handle). This is the approach I'm taking, where I currently have to map against an existing database's SPs, but will later migrate to a new ORM-based system.

流心雨 2024-07-19 11:51:37

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

最近,当我工作的公司从 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 而言,我我不熟悉它...抱歉。 希望这可以帮助。

Maybe I'm not understanding your question correctly, but it sounds to me like you need to implement something like the "Factory Pattern".

I recently used the factory pattern to code (c#) to two data layers when the company I work for was switching from JDE to SAP. I was able to flip a config switch to switch between the two data layers, and the GUI wouldn't know any different.

Here's a couple links I found:

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

As far as NHibernate goes, I'm not familiar with it... sorry. Hope this helps.

喜你已久 2024-07-19 11:51:37

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

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

Hard to recommend without knowing the full picture, but.... You can create an abstruction in the SPs by having SP return identical dataset for both table structures.

Another abstruction I am thinking of, is you can actually specify different hybernate mapping files, and initialize Hibernate with a different file depending on what database you connect to.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文