当把业务层和数据层分开时,在哪里对实体进行限制?[英] Where to put restrictions on entities when separating Business layer from Data Layer

本文是小编为大家收集整理的关于当把业务层和数据层分开时,在哪里对实体进行限制?的处理方法,想解了当把业务层和数据层分开时,在哪里对实体进行限制?的问题怎么解决?当把业务层和数据层分开时,在哪里对实体进行限制?问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

我正在尝试为我的大型 ASP.NET MVC 应用程序创建业务层和数据层.因为这是我第一次尝试这种规模的项目,所以我正在阅读一些书籍,并努力小心地将事情正确地分开.通常我的应用程序混合了业务逻辑和数据访问层,多个业务实体交织在一个类中(当我试图弄清楚在哪里添加东西时,这让我有几次困惑).

我一直在阅读的大部分内容是将业务层和数据层分开.这看起来一切都很好而且很花哨,但我无法准确地想象在某些情况下如何做到这一点.例如,假设我正在创建一个允许管理员向系统添加新产品的系统:

public class Product
{ 
   public int Id { get; private set; }
   public string Name { get; set; }
   public decimal Price { get; set; }
}

然后我通过创建一个存储库来分离数据访问

public class ProductRepository
{
   public bool Add(Product product);
}

假设我想要求产品名称至少包含 4 个字符.我看不出如何干净地做到这一点.

我的一个想法是扩展 Name 的 set 属性,并且仅在它的长度为 4 个字符时才设置它.但是,创建产品的方法无法知道名称没有被设置,除了 Product.Name != 无论他们传入什么.

我的另一个想法是把它放在存储库的 Add() 方法中,但是我的业务逻辑和数据逻辑就在那里,这也意味着如果 Add 调用失败我不知道是不是业务逻辑失败或因为 DAL 失败(这也意味着我无法使用模拟框架对其进行测试).

我唯一能想到的就是将我的 DAL 东西放在第 3 层中,该层从存储库中的 Add() 方法调用,但我在书中的任何域建模示例中都没有看到这一点或在网络上(至少我见过).当我不确定是否需要它时,它还会增加域模型的复杂性.

另一个示例是要确保名称仅由一个产品使用.这会放在 Product 类、ProductRepository Add() 方法中,还是放在哪里?

附带说明一下,我计划使用 NHibernate 作为我的 ORM,但是,为了完成我想要的(理论上)我使用什么 ORM 并不重要,因为 TDD 应该能够将它全部隔离.

提前致谢!

推荐答案

我通常使用分层架构来解决这个问题.这个怎么做?你基本上有以下(理想情况下)VS项目:

  • 表示层(UI 内容所在的位置)
  • 业务层(实际业务逻辑所在的位置)
  • 数据访问层(您与底层 DBMS 通信的地方)

为了将它们全部解耦,我使用所谓的接口层 s.t.最后我有

  • 表示层(UI东西驻留)
  • IBusiness 层(包含业务层)
  • 业务层(其中实际的业务逻辑驻留)
  • IDataAccess 层(包含DAO 层的接口)
  • 数据访问层(您沟通的地方与您的底层 DBMS)

这非常方便,并创建了一个很好的解耦架构.基本上,您的表示层只访问接口而不是实现本身.要创建相应的实例,您应该使用工厂或最好使用一些依赖注入库(Unity 对 .Net 应用程序或 Spring.Net).

这对您应用的业务逻辑/可测试性有何影响?
详细编写所有内容可能太长了,但如果您担心设计的可测试性良好,则绝对应该考虑依赖注入库.

使用 NHibernate,...无论 ORM
拥有一个通过接口与其他层完全分离的 DAO 层,您可以使用任何背后的技术来访问您的底层数据库.您可以根据需要直接发出 SQL 查询或使用 NHibernate.好消息是它完全独立于您的应用程序的其余部分.您可以通过手动编写 SQL 来开始今天的活动,明天将您的 DAO dll 与使用 NHibernate 的 DAO dll 交换,而无需对您的 BL 或表示层进行任何更改.
此外,测试您的 BL 逻辑很简单.您可能有这样的课程:

public class ProductsBl : IProductsBL
{

   //this gets injected by some framework
   public IProductsDao ProductsDao { get; set; }

   public void SaveProduct(Product product)
   {
      //do validation against the product object and react appropriately
      ...

      //persist it down if valid
      ProductsDao.PersistProduct(product);
   }

   ...
}

现在您可以通过在测试用例中模拟 ProductDao 来轻松测试 SaveProduct(...) 方法中的验证逻辑.

本文地址:https://www.itbaoku.cn/post/1793951.html