服务层正在重复我的存储库

时间:2010-05-21 17:01:18

标签: asp.net-mvc nhibernate repository domain-driven-design service

我正在使用asp.net mvc,NHibernate和DDD开发一个应用程序。我有一个服务层,由我的应用程序的控制器使用。一切都在使用Unity注入依赖项(存储库中的ISessionFactory,控制器中服务和服务中的存储库)并且工作正常。

但是,我很需要一个服务方法来获取我的存储库中的对象,就像这样(在服务类中):

public class ProductService {

   private readonly IUnitOfWork _uow;
   private readonly IProductRepository _productRepository;

   public ProductService(IUnitOfWork unitOfWork, IProductRepository productRepository) {
      this._uow = unitOfWork;
      this._productRepository = productRepository;
   }

   /* this method should be exists in DDD ??? It's very common */
   public Domain.Product Get(long key) {
      return _productRepository.Get(key);
   }

   /* other common method... is correct by DDD ? */
   public bool Delete(long key) {
      usign (var tx = _uow.BeginTransaction()) {
         try 
         {
           _productRepository.Delete(key);
           tx.Commit();
           return true;
         } catch {
           tx.RollBack();
           return false;
         }        
      }
   }

   /* ... others methods ... */

}

这个代码是否正确DDD?对于每个Service类,我都有一个Repository,对于每个服务类,我需要为一个实体做一个“Get”方法吗?

谢谢你们

干杯

2 个答案:

答案 0 :(得分:9)

您的ProductService看起来不像是按照域驱动设计原则。如果我理解正确,它是Presentation和Domain之间Application层的一部分。如果是这样,ProductService上的方法应该对产品有商业意义。

让我们谈谈删除产品。它就像在数据库上执行删除一样简单(NHibernate,还是其他什么?)我认为不是。那些参考待删除产品的订单怎么样?等等等等。顺便说一句,Udi Dahan在删除实体上写了great article

最重要的是,如果您的应用程序如此简单以至于服务确实复制了您的存储库并且仅包含CRUD操作,那么您可能不应该执行DDD,丢弃您的存储库并让服务对实体进行操作(这将是简单的数据那种情况下的容器。)

另一方面,如果存在复杂的行为(例如处理'已删除'产品的行为),那么DDD路径就有了一点,我强烈主张这样做。

PS。尽管采用哪种方法(DDD与否),我最终会鼓励您使用一些面向方面编程来处理与事务和异常相关的事情。最终会遇到许多方法,例如具有相同TX和异常处理代码的DeleteProduct。

答案 1 :(得分:1)

从我的角度看,这看起来是正确的。我真的不喜欢在我的asp.net MVC项目中反复重复服务和存储库方法名称,所以我选择了通用存储库方法/模式。这意味着我真的只需要在我的存储库中使用一个或两个Get()方法来检索我的对象。这对我来说是可行的,因为我正在使用Entity Framework,我只是让我的存储库的get()方法返回一个IQueryable。然后我可以做以下事情:

Product product = from p in _productRepository.Get() where p.Id == Id select p; 

您可以使用linq在NHibernate中复制此内容 - > NHibernate的。

<小时/> 编辑:这适用于DDD,因为只要我使用的数据库(Nhibernate,EF等)支持IQueryable,这仍然允许我交换我的DAL /存储库。

我不确定如何在没有IQueryable的情况下执行通用存储库,但是您可以使用委托/ lambda函数来合并它。

<小时/> Edit2:以防万一我没有正确回答你的问题,如果你问是否应该从服务中调用你的存储库的Get()方法,那么是的,那就是正确的DDD设计同样。原因是服务层应该处理所有业务逻辑,因此它确切地确定要检索的数据和数据(例如,您是按字母顺序,无序等方式...)。这也意味着它可以在需要加载后执行验证或在删除和/或保存之前进行验证。

这意味着服务层并不关心数据的存储和检索方式,它只决定存储和检索哪些数据。然后,它调用存储库来正确处理请求,并以服务层告诉它的方式检索/存储数据。因此,您可以正确地分离关注点。