【问题标题】:Adding a Business Layer to ADO .NET Entity Framework向 ADO .NET Entity Framework 添加业务层
【发布时间】:2009-01-11 14:39:49
【问题描述】:

我正在开发我的第一个 .NET 项目(.NET 3.5、ADO.NET 和 C#)。我们已经构建了实体模型,并正在尝试构建一个干净的业务对象层。

我们已经有了我们的基本实体模型,我们希望将某些业务级语义添加到默认数据访问器(导航属性等)。

例如,假设我们在PersonBankAccounts 之间存在多对多关系。假设我们想在业务层添加冻结帐户的功能。我们现在希望能够从 Person 导航到:

  • 他们所有的银行账户,
  • 他们未冻结的银行账户,以及
  • 他们被冻结的银行账户。

当然,我们希望将名义情况设为默认值:如果我导航 Person.BankAccounts(),我希望它返回他们未冻结的帐户。我可以添加导航属性Person.FrozenBankAccounts()Person.AllBankAccounts()

我们提出的两种方法似乎都有相当多的代码味道。

  1. 我们找不到覆盖实体模型方法的方法。所以,留下Person.BankAccounts() 作为返回所有银行账户的访问者。然后我们添加一个Person.FrozenBankAccounts() 和一个Person.NonFrozenBankAccounts()
  2. 在代码库中添加另一个显式层,用于封装对 BankAccounts 的所有访问。

对于方法 1,问题在于名义业务案例(访问未冻结的银行账户)是该批次中最不直观的方法名称。

使用方法 2,当我们从实体模型层子类化对象时,我们必须重写每个方法以确保它不会从底层返回对象。所以我们创建了一个BL_Person,它有一个BankAccounts() 方法,它返回一个BL_BankAccount 对象的集合。但在这种情况下,所有这些代码都显得有点傻。

有没有比我们考虑过的两种方法更好的方法?如果没有更好的方法,我概述的两种方法中的哪一种似乎是更好的解决方案(鉴于我们需要处理 50 多个类)?

注意:在进行网络搜索时,我确实找到了一封致微软的公开信,标题为ADO .NET Entity Framework Vote of No Confidence,这似乎暗示着没有一个好的方法来明确分离关注点.

【问题讨论】:

    标签: .net entity-framework .net-3.5 orm ado.net-entity-data-model


    【解决方案1】:

    我没有使用 LINQ to Entities 的经验,但您的问题敲响了警钟。在我的上一个项目中,我在使用另一个 ORM 时遇到了几乎相同的问题。我没有让业务对象层的客户端直接使用 ORM 生成的类或复制所有类并实现大量转发功能,而是定义了接口。您的业​​务对象层的客户端只能看到这些接口,而您的实体类将实现这些接口,具有以下优点:

    • 在直截了当的情况下(无业务逻辑),接口的开发开销最小。对于大多数成员,您不需要实现转发功能,只需从接口“派生”实体类并完成它即可
    • 在您提到的情况下,您可以在接口中拥有一个属性 BankAccounts,并通过显式接口实现将其转发给实施实体的 NonFrozenBankAccounts。当然,您也可以添加任何类型的支票
    • 另外一个好处是,您可以轻松地交换底层持久层,而无需明显更改客户端代码的任何内容

    【讨论】:

      【解决方案2】:

      您可以添加两个从 Account 继承的新实体类型
      - RegularAccount 和 FrozenAccount
      并将您的 IsFrozen 字段添加为继承条件(每个层次结构的表)。

      然后您可以删除从“Person”到“Account”的关联并创建两个新关联:

      Person 到 RegularAccount,命名人“Accounts”的导航属性。

      Person to FrozenAccount,命名人“FrozenAccounts”的导航属性。

      【讨论】:

        【解决方案3】:

        一种方法是这样的:

        1. 定义您的 AllBankAccounts 属性(甚至可能将其设为私有)。
        2. 在部分 Person 类中定义 BankAccounts 属性。该属性可以使用 LINQ 以 AllBankAccounts 的形式表示,即 AllBankAccounts.Where(a => !a.IsFrozen)
        3. 在部分 Person 类中定义 FrozenBankAccounts 属性,如步骤 2。

        希望对您有所帮助。

        【讨论】:

          【解决方案4】:

          抛弃 EF 转而使用 NHibernate

          NHibernate 的方式是:您创建业务对象,然后告诉 NHibernate 如何将这些业务对象保存到数据库中。业务对象本身知道它们是如何保存或加载的,或者不知道如何使用 NHibernate。这叫做“执着无明”。另外,您可以告诉 NHibernate 以几乎任何您喜欢的方式保存和加载您的业务对象。它对您描述的场景有很好的支持。

          停止编写数据访问层并停止生成代码。使用real man's ORM

          【讨论】:

          • 不错的方法,但是也可以使用 EF4 实现。
          猜你喜欢
          • 2013-10-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-04
          相关资源
          最近更新 更多