代码之家  ›  专栏  ›  技术社区  ›  Felipe Oriani

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

  •  2
  • Felipe Oriani  · 技术社区  · 14 年前

    我正在使用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?对于每个服务类,我都有一个存储库,对于每个服务类,我需要为一个实体做一个方法“get”?

    谢谢大家

    干杯

    2 回复  |  直到 14 年前
        1
  •  1
  •   KallDrexx    14 年前

    从我的角度看是正确的。我真的不喜欢在我的ASP.NET MVC项目中反复地重复服务和存储库方法名,所以我选择了一种通用的存储库方法/模式。这意味着我在存储库中只需要一两个get()方法来检索我的对象。这对我来说是可能的,因为我正在使用实体框架,并且我只是让存储库的get()方法返回一个iqueryable。然后我可以做以下的事情:

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

    您可能可以用linq->nhibernate在nhibernate中复制这个。


    编辑: 这对DDD有效,因为这仍然允许我交换DAL/存储库,只要我使用的数据库(nhibernate、ef等)支持iqueryable。

    我不知道如何在不使用iQueryable的情况下创建通用存储库,但是您可能能够使用delegates/lambda函数来合并它。


    编辑2: 以防我没有正确回答你的问题,如果你问你是否应该从服务调用你的存储库的get()方法,那么是的,这也是正确的DDD设计。原因是服务层应该处理您的所有业务逻辑,因此它确切地决定了如何以及要检索哪些数据(例如,您希望它按字母顺序、无序等…)。它还意味着,如果需要,它可以在加载后执行验证,或者在删除和/或保存之前执行验证。

    这意味着服务层并不关心数据是如何存储和检索的,它只决定存储和检索什么数据。然后,它调用存储库来正确处理请求,并按照服务层的指示检索/存储数据。因此,您可以正确地分离关注点。

        2
  •  9
  •   Szymon Pobiega    14 年前

    您的产品服务看起来不像遵循域驱动的设计原则。如果我理解正确,它是表示和域之间的应用层的一部分。如果是这样,那么productService方法应该对产品具有业务意义。

    我们来谈谈删除产品。它是否和在数据库上执行删除一样简单(nhibernate或其他什么方法?)我想不是。引用要删除的产品的订单如何?等等。顺便说一句,乌迪达汉写了一篇 great article 删除实体时。

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

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

    尽管您最终会采用哪种方法(DDD或不DDD),我还是建议您使用一些面向方面的编程来处理事务和异常相关的东西。您将最终找到许多方法,如具有相同Tx和异常处理代码的DeleteProduct。