DDD:实体的集合和存储库 [英] DDD: entity's collection and repositories

查看:117
本文介绍了DDD:实体的集合和存储库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有

public class Product: Entity
{
   public IList<Item> Items { get; set; }
}

假设我想找到一件物品,物品最大...我可以添加方法 Product.GetMaxItemSmth()并使用Linq(在Items中选择i.smth).Max())或手动循环或其他方式。现在,问题在于这会将整个集合加载到内存中。

Suppose I want to find an item with max something... I can add the method Product.GetMaxItemSmth() and do it with Linq (from i in Items select i.smth).Max()) or with a manual loop or whatever. Now, the problem is that this will load the full collection into memory.

正确的解决方案是执行特定的数据库查询,但域实体无权访问仓库,对不对?所以我要么

The correct solution will be to do a specific DB query, but domain entities do not have access to repositories, right? So either I do

productRepository.GetMaxItemSmth(product)

(这很丑,不是吗?),或者即使实体可以访问存储库,我也使用实体<< c $ c> IProductRepository / p>

(which is ugly, no?), or even if entities have access to repositories, I use IProductRepository from entity

product.GetMaxItemSmth() { return Service.GetRepository<IProductRepository>().GetMaxItemSmth(); }

这也很丑陋,是重复的代码。我什至可以幻想并扩展

which is also ugly and is a duplication of code. I can even go fancy and do an extension

public static IList<Item> GetMaxItemSmth(this Product product)
{
   return Service.GetRepository<IProductRepository>().GetMaxItemSmth();
}

这样做更好是因为它不会真正使存储库中的实体混乱。 ..,但仍会重复方法。

which is better only because it doesn't really clutter the entity with repository... but still does method duplication.

现在,这是是否使用 product.GetMaxItemSmth()或 productRepository.GetMaxItemSmth(product)...。我是否错过了DDD中的某些内容?这里正确的方法是什么?只需使用 productRepository.GetMaxItemSmth(product)

Now, this is the problem of whether to use product.GetMaxItemSmth() or productRepository.GetMaxItemSmth(product)... again. Did I miss something in DDD? What is the correct way here? Just use productRepository.GetMaxItemSmth(product)? Is this what everyone uses and are happy with?

我只是觉得不正确...如果我无法访问产品的商品来自产品本身,为什么我在产品中根本需要此收藏???然后,如果 Product 不能使用特定查询并且在没有性能损失的情况下访问其集合,可以做任何有用的事情吗?

I just don't feel it is right... if I can't access a product's Items from the product itself, why do I need this collection in Product at all??? And then, can Product do anything useful if it can't use specific queries and access its collections without performance hits?

当然,我可以使用一种效率较低的方法,别介意,并且当它变慢时,我会将存储库调用作为一种优化注入到实体中……但是,即使这样听起来也不对,是吗?

Of course, I can use a less efficient way and never mind, and when it's slow I'll inject repository calls into entities as an optimization... but even this doesn't sound right, does it?

要提一件事,也许它不是DDD ...但是我需要在Product中使用IList才能使用Fluent NHibernate生成数据库模式。

One thing to mention, maybe it's not quite DDD... but I need IList in Product in order to get my DB schema generated with Fluent NHibernate. Feel free to answer in pure DDD context, though.

更新:此处描述了一个非常有趣的选项: http://devlicio.us/blogs/billy_mccafferty/archive/2007 /12/03/custom-collections-with-nhibernate-part-i-the-basics.aspx ,不仅可以处理与数据库相关的集合查询,还可以帮助进行集合访问控制。

UPDATE: a very interesting option is described here: http://devlicio.us/blogs/billy_mccafferty/archive/2007/12/03/custom-collections-with-nhibernate-part-i-the-basics.aspx, not only to deal with DB-related collection queries, but also can help with collection access control.

推荐答案

具有集合具有 GetXXX()方法都是正确的。

Having an Items collection and having GetXXX() methods are both correct.

为简单起见,您的实体不应该直接访问存储库。但是,它们可以通过查询规范具有间接引用。请查看埃里克·埃文斯(Eric Evans)书中的第229页。这样的事情:

To be pure, your Entities shouldn't have direct access to Repositories. However, they can have an indirect reference via a Query Specification. Check out page 229 of Eric Evans' book. Something like this:

public class Product
{
    public IList<Item> Items {get;}

    public int GetMaxItemSmth()
    {
        return new ProductItemQuerySpecifications().GetMaxSomething(this);
    }
}

public class ProductItemQuerySpecifications()
{
   public int GetMaxSomething(product)
   {
      var respository = MyContainer.Resolve<IProductRespository>();
      return respository.GetMaxSomething(product);
   }
}

如何获得对存储库的引用是您的选择(DI,服务定位器等)。

How you get a reference to the Repository is your choice (DI, Service Locator, etc). Whilst this removes the direct reference between Entity and Respository, it doesn't reduce the LoC.

通常,我只在很早就引入它,前提是我知道它的数量。 GetXXX()方法将来会引起问题。否则,我将其留给以后进行重构。

Generally, I'd only introduce it early if I knew that the number of GetXXX() methods will cause problems in the future. Otherwise, I'd leave it for a future refactoring exercise.

这篇关于DDD:实体的集合和存储库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆