我已经探索BDD/DDD和作为的后果试图拿出一个适当执行的储存库的图形。迄今为止,它已经很难找到一个协商一致的最佳方式实现这一点。我试着把它下下面的变化,但是我不确定这是最好的办法。

对于参考,我要建一个ASP。软应用程序,与它能够作为后端。

public interface IRepository<T> {
        // 1) Thin facade over LINQ
        T GetById(int id);
        void Add(T entity);
        void Update(T entity);
        void Remove(T entity);
        IQueryable<T> Find();
        // or possibly even
        T Get(Expression<Func<T, bool>> query);
        List<T> Find(Expression<Func<T, bool>> query);
}

public interface IRepository<T> {
        // 2) Custom methods for each query
        T GetById(int id);
        void Add(T entity);
        void Update(T entity);
        void Remove(T entity);
        IList<T> FindAll();
        IList<T> FindBySku(string sku);
        IList<T> FindByName(string name);
        IList<T> FindByPrice(decimal price);
        // ... and so on
}

public interface IRepository<T> {
        // 3) Wrap NHibernate Criteria in Spec pattern
        void Add(T entity);
        void Update(T entity);
        void Remove(T entity);
        IList<T> FindAll();
        IList<T> FindBySpec(ISpecification<T> specification);
        T GetById(int id);
}


public interface IRepository<T> {
        // 4) Expose NHibernate Criteria directly
        T GetById(int id);
        void Add(T entity);
        void Update(T entity);
        void Remove(T entity);
        IList<T> FindAll();
        IList<T> Find(ICriteria criteria);
        // .. or possibly
        IList<T> Find(HQL stuff);
}

我的初步想法是,

1)是伟大的,从效率的观点,但我可能会惹上麻烦的事情变得更复杂。

2)似乎非常繁琐,并可能会与一个非常拥挤的班级,但无提供一个高度分离间我域的逻辑和数据层,我喜欢。

3)似乎难以前更多的工作来编写查询,但是限制交叉污染,只是规范层。

4)我最不喜欢的,但是可能最直接的执行和可能的大多数数据库的有效对复杂的查询,虽然它把很多的责任上的调用的代码。

有帮助吗?

解决方案

我认为他们都是不错的选择(如果你不想把自己束缚于nhibernate,那么可能只有4个),并且你似乎根据你当前的努力分析了自己的优缺点。 不要在这方面打败自己

我正在研究2到3之间的混合物我想:

public interface IRepository<T> 
{
        ...
        IList<T> FindAll();
        IList<T> FindBySpec(ISpecification<T> specification);
        T GetById(int id);
}

public interface ISpecificRepository : IRepository<Specific> 
{
        ...
        IList<Specific> FindBySku(string sku);
        IList<Specific> FindByName(string name);
        IList<Specific> FindByPrice(decimal price);
}

还有一个Repository(of T)基类。

其他提示

还有一个很好的论据是<!>“;以上都没有<!>做法。

通用存储库的问题在于,您假设系统中的所有对象都支持所有四种CRUD操作:创建,读取,更新,删除。但在复杂系统中,您可能只有少数几个操作的对象。例如,您可能具有只读对象或已创建但从未更新的对象。

您可以将IRepository接口分解为小型接口,用于读取,删除等,但这很快就会变得混乱。

Gregory Young提出了一个很好的论据(从DDD /软件分层的角度来看),每个存储库应该只支持特定于域对象或您正在使用的聚合的操作。这是关于通用存储库

对于另一种观点,请参阅此Ayende 博客文章

我们正在做的一件事是我们所有的存储库都有不同的需求,所以我们正在创建一个接口集合:

public interface IReadOnlyRepository<T,V>
{
   V Find(T);
}

在此示例中,只读存储库只是从数据库获取。 T,V的原因是V表示存储库返回的内容,T表示传入的内容,因此您可以执行以下操作:

public class CustomerRepository:IReadOnlyRepository<int, Customer>, IReadOnlyRepository<string, Customer>
{
    public Customer Find(int customerId)
    {
    }

    public Customer Find(string customerName)
    {
    }
}

我还可以为Add,Update和Delete创建单独的界面。这样,如果我的存储库不需要该行为,那么它就不会实现该接口。

我是一个国际仁爱基金会的风扇,1因为我可以创建的过滤器和呼扩展的方法比我可以适用于IQueryable<>返回值找到方法。我一直延伸方法在数据层,然后建造的飞行在业务层。(不完全纯粹的,当然.)

当然,当该系统的稳定我的选择作出特定寻找方法使用相同的扩展的方法和优化使用Func<>.

在Linq中使用NH时,您的存储库可以是:

session.Linq<Entity>()

规范是涉及的事项:

IQueryable<Entity>

如果你愿意的话,你可以将它全部展开,但这是抽象抽象的很多平凡的工作。

简单就是好。是的,NH做数据库,但它提供了更多的模式。除了DAL之外,不依赖于NH远非罪恶。

我认为这取决于您的需求。将存储库与您考虑使用的其他设计模式结合使用非常重要。最后,它取决于您对存储库的期望(使用它的主要原因是什么)。

您是否需要创建严格的图层(例如,您将来需要将NHibernate替换为Entity Framework)?您是否想要特别针对存储库方法编写测试?

没有最好的方法来创建存储库。只有几种方式,它绝对取决于您,最符合您需求的是什么。

保存库

LosTechies的Jimmy Bogard的相关文章

http:// www .lostechies.com /博客/ jimmy_bogard /存档/ 2009/09/10 /枯萎最repository.aspx

此外,另一篇快速文章,其中一些评论表明版本#2实际上是DOA模式,而不是存储库。

http://fabiomaulo.blogspot.com/2009/06 /linq-and-repository.html

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top