单个类有两个数据库

时间:2011-05-24 21:35:27

标签: c# database reflection .net-4.0 advantage-database-server

我有两部分申请。一部分是Web应用程序(C#4.0),它在带有托管MSSQL数据库的托管计算机上运行。这很好,很标准。另一部分是Windows应用程序,它在我们的网络上本地运行,并访问我们的主数据库(Advantage)和Web数据库。该网站无法访问Advantage数据库。

目前这个设置工作正常(假设网络正常工作),但我们现在正在重建网站并将其从Web Forms /.NET 2.0 / VB站点升级到MVC3 / .NET 4.0 / C#网站。作为重建的一部分,我们添加了许多新表,其中内部数据库包含所有数据,并且Web数据库具有其子集。

在内部应用程序中,数据库中的表由使用反射和属性标志填充自身的类表示。例如:

[AdvantageTable("warranty")]
public class Warranty : AdvantageTable
{
    [Advantage("id", IsKey = true)]
    public int programID;
    [Advantage("w_cost")]
    public decimal cost;
    [Advantage("w_price")]
    public decimal price;

    public Warranty(int id)
    {
        this.programID = id;
        Initialize();
    }
}

AdvantageTable类的Initialize()方法使用反射基于所有键及其值构建查询,然后根据指定的数据库列填充每个字段。更新工作类似 - 我们在任何对象上调用AdvantageTable.Update(),它处理所有数据库写入。它工作得很好,隐藏了所有标准的CRUD,并允许我们在添加新表时快速创建新类。我们宁愿不改变它,但如果有一个需要它的解决方案,我不会完全排除它。

Web数据库需要具有此表,但不需要成本数据。我可以创建一个由Web数据库支持的单独类(通过存储过程,反射,LINQ-TO-SQL,ADO数据对象等),但Warranty对象中可能还有其他功能,我希望它们的行为方式相同无论是从网站还是内部应用程序调用它,无需维护两组代码。例如,我们可能会改变我们如何决定哪种保修适用于产品的逻辑 - 我只需要在一个地方创建和测试,而不是两个。

所以我的问题是:有人能想出一个很好的方法来允许这个类有时会从Advantage数据库和Web数据库中填充吗?这不仅仅是连接字符串的问题,因为他们有两种截然不同的访问方法(即使不是反射)。我考虑将[Web("id")]类型标记添加到Advantage标记中,并且只将它们放在Web数据库中存在的字段中以指定其列,然后使用某种类型的开关来控制使用哪组逻辑来读取/写作,但我觉得这会很痛苦(这个方法是否安全?这个怎么在实例化之前设置标志?)。所以我没有自己喜欢的想法,并怀疑有一个我甚至都不知道存在的解决方案。有什么输入吗?

2 个答案:

答案 0 :(得分:2)

我认为根本问题在于您希望将业务逻辑放在Warranty对象中,后者是一个数据层对象。你真正想要做的是拥有两个数据源支持的通用数据契约(在这种情况下可以是一个接口),逻辑封装在可以与任一数据源一起运行的单独的类/层中。通过建立业务层可以使用的通用数据协定,无论数据如何被提取,单个数据类尝试使用两个不同的数据源来解决这个问题。

因此,在您的示例中,您可能拥有AdvantageWarranty和WebWarranty,两者都实现了IWarranty。您有一个单独的WarrantyValidator类可以在任何IWarranty上运行,以告诉您保修在特定条件下是否仍然有效。顺便提一下,如果您想在WarrantyValidator类中对业务逻辑进行单元测试,这可以为您提供一种存根数据的好方法。

答案 1 :(得分:0)

我最终提出的解决方案是双重的。首先,我使用Linq-to-sql为每个Web表生成对象。然后,我从AdvantageTable派生了一个名为AdvantageWebTable<TABLEOBJECT>的新类,它包含特定于Web的代码,并添加了特定于Web的属性。所以现在这个课程看起来像这样:

[AdvantageTable( “保修”)]

public class Warranty : AdvantageWebTable<WebObjs.Warranty>
{
    [Advantage("id", IsKey = true)][Web("ID", IsKey = true)]
    public int programID;
    [Advantage("w_cost")][Web("Cost")]
    public decimal cost;
    [Advantage("w_price")][Web("Price")]
    public decimal price;

    public Warranty(int id)
    {
        this.programID = id;
        Initialize();
    }
}

在保存到Web数据库之前,还有用于填充仅限Web的字段的钩子,并且会有(但是我还没有需要它)一个LoadFromWeb()函数,它使用反射来填充田野。

相关问题