一个大的存储库与许多小存储库?

时间:2011-06-09 21:45:29

标签: c# asp.net-mvc design-patterns architecture

我的数据库中有几个产品表:

  • ProductTypes
  • ProductCategories
  • ProductCategoryItems
  • ProductInventory

我现在看到它的方式,我可以制作具有以下方法的IProduct:

  • FindAllTypes()
  • FindAllCategories(int typeId)
  • FindAllItems(int categoryId)

或者,我可以将每个分开来模仿表结构:IProductType,IProductCategory等。

是否有理由选择一个而不是另一个?

4 个答案:

答案 0 :(得分:13)

存储库的想法是委托每个人负责一个实体。在这种情况下,建议为每个实体建立一个存储库。您也可以使用大型存储库,但这不是最佳解决方案。最后,你会得到一个有很多方法的巨大课程,而且非常紧密。也难以维修。

答案 1 :(得分:6)

我认为拥有一个庞大的存储库并不是一个好主意,那么你基本上就拥有一个可以完成所有工作的数据访问神类。

我希望有一个基础Repository<T>来执行常见操作,例如GetByIdGetAll。我通常都有我的所有存储库继承这个基类以获得免费的常用方法,所以我不必继续重写相同的代码。

答案 2 :(得分:4)

在我看来,这在很大程度上取决于业务领域模型,确定您的主要业务实体是非常重要的。数据库中的每个表都不一定直接映射到业务实体。表只是关系数据库的规范化方式中一个或多个实体的表示。

尝试将您的域模型描绘成超出规范化关系数据库的限制,是否真的有多个业务概念?存储库应围绕固体,整体,一流的业务实体构建。

我的建议是拥有一个IProductRepository,其中包含实现CRUD操作的必要方法,并根据需要进行扩展。您不希望得到过于雄心勃勃的界面,因为您可能不需要大部分界面,这可能是一种负担。接口的重要一点是将代码与持久性模式分离,因此后者可以灵活地在它们之间切换。

也许在未来,企业需要发展到更详细的代表 - 例如 - 产品的供应商,在那一刻,您将使用您的良好判断来决定代表一个重要的商业实体,值得一个专用存储库与否。

希望这有帮助。

答案 3 :(得分:3)

我不赞同其他人(编辑:除了艾萨克)。小型存储库是一个外观(不是模式)。

如果实体类型是耦合的(彼此具有导航属性),那么它们实际上是不可分离的。

修改一个实体类型并提交更改可能会将更改提交给其他实体。

此外,您无法在同一工作单元上创建任何小型存储库, 因为ORM只有有限数量的实体映射到数据库。

将您的模型划分为可分离的域,并为每个域创建一个特定的工作单元。

在这些工作单元上,为您可能需要立即访问的每种实体类型创建aggregate roots

每个root都应该有特定类型的add,remove,getbykeys,query等方法。

工作单元应该有commit更改和相似的方法。

每个根类似于其他人提到的小型存储库,但是,工作单元是真正的中型存储库(其模型可能有多种类型)。

示例:

// Create one of these
interface IUnitOfWork
{
    void Commit();
}

// Create one of these
interface IEntitySet<TEntity> where TEntity : class
{
    void Add(TEntity entity);
    void Remove(TEntity entity);
    TEntity Create<TSpecificEntity>() where TSpecificEntity : TEntity;

    IQueryable<TEntity> Query();
}

// Create one of these per entity type
interace IEntitySetOfTEntity1 : IEntitySet<Entity1>
{
    TEntity1 GetByKeys(int key1);
}

interace IEntitySetOfTEntity2 : IEntitySet<Entity2>
{
    TEntity1 GetByKeys(short key1, short key2);
}

// Create one of these per separatable domain
interface IDomain1UnitOfWork : IUnitOfWork
{
    IEntitySetOfTEntity1 Entity1s
    {
        get;
    }

    IEntitySetOfTEntity2 Entity2s
    {
        get;
    }
}

所有这些接口及其实现都可以自动生成。

这些接口及其实现的重量非常轻,绝不是“具有大量方法的巨大类”。由于它们可以自动生成,因此维护很容易。

具体功能可以通过以下方式添加到接口IDomain1UnitOfWork,IEntitySetOfTEntity1等中:
一个。扩展方法
湾部分接口和类(不太推荐,因为这会导致DAL不太清晰)

如果使用扩展方法将GetByKeys()方法添加到IEntitySet&lt; Entity1&gt;中,则可以忽略IEntitySetOfTEntity1之类的接口。