Mic*_*ook 36 c# bdd domain-driven-design repository-pattern
我一直在探索BDD/DDD,因此试图找到Repository模式的正确实现.到目前为止,很难就实现这一点的最佳方式达成共识.我试图将其归结为以下变化,但我不确定哪种方法最好.
作为参考,我正在构建一个以NHibernate作为后端的ASP.MVC应用程序.
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);
}
Run Code Online (Sandbox Code Playgroud)
我最初的想法是
1)从效率的角度来看是很好的,但随着事情变得更加复杂,我可能会遇到麻烦.
2)看起来非常繁琐,可能最终会出现一个非常拥挤的类,但除此之外,我喜欢的域逻辑和数据层之间存在高度分离.
3)前面看起来很困难,编写查询的工作也比较多,但是只限于Specs层的交叉污染.
4)我最不喜欢的,但可能是最直接的实现,可能大多数数据库对复杂查询有效,尽管它对调用代码负有很多责任.
Fre*_*oux 10
我认为它们都是不错的选择(如果你不想把自己束缚于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);
}
Run Code Online (Sandbox Code Playgroud)
还有一个Repository(of T)基类.
我们正在做的一件事是我们所有的存储库都有不同的需求,所以我们创建了一个接口集合:
public interface IReadOnlyRepository<T,V>
{
V Find(T);
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,只读存储库只是从数据库获取.T,V的原因是V表示存储库返回的内容,T表示传入的内容,因此您可以执行以下操作:
public class CustomerRepository:IReadOnlyRepository<int, Customer>, IReadOnlyRepository<string, Customer>
{
public Customer Find(int customerId)
{
}
public Customer Find(string customerName)
{
}
}
Run Code Online (Sandbox Code Playgroud)
我还可以为Add,Update和Delete创建单独的接口.这样,如果我的存储库不需要该行为,那么它就不会实现该接口.