1

我有一个两部分的应用程序。一部分是一个 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 数据对象等),但保修对象中可能还有其他功能,我希望以相同的方式运行无论是从网站调用还是从内部应用调用,都不需要维护两套代码。例如,我们可能会改变我们决定对产品适用何种保修的逻辑——我希望只需要在一个地方而不是两个地方创建和测试它。

所以我的问题是:谁能想到一个好方法来允许这个类有时从 Advantage 数据库中填充,有时从 Web 数据库中填充? 这不仅仅是连接字符串的问题,因为它们有两种非常不同的访问方法(甚至除了反射之外)。我考虑将[Web("id")]类型标签添加到 Advantage 标签中,并且只将它们放在 Web 数据库中存在的字段上以指定其列,然后使用某种开关来控制用于读取/写入的逻辑集,但我感觉那会很痛苦(这种方法对网络安全吗?如何在实例化之前设置标志?)。所以我没有我喜欢的想法,并怀疑有一个我什至不知道存在的解决方案。有输入吗?

4

2 回答 2

2

我认为根本问题是你想把业务逻辑放在 Warranty 对象中,这是一个数据层对象。您真正想要做的是拥有两个数据源都支持的通用数据契约(在这种情况下可能是一个接口),其逻辑封装在一个单独的类/层中,可以与任一数据源一起操作。这通过建立一个您的业务层可以使用的通用数据契约来回避让单个数据类尝试使用两个不同的数据源进行操作的问题,而不管数据是如何提取的。

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

于 2011-05-24T21:45:02.387 回答
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()使用反射来填充字段的函数。

于 2011-07-08T17:53:43.257 回答