我正在考虑改进我当前的存储库GetAll方法实现,并编写了下面的代码。我试图在谷歌中找到这种方法的想法,但没有成功。因此,请检查代码,并帮助我回答下面的一些问题。以下是简化的示例:
class Service
{
public void DoOperation()
{
// Let's say we need to retrieve users by criteria
var items = UnitOfWork
.Over<User>() // Get repository of User
.GetAll() // Start querying
// If we need simple WHERE then use:
.Where(x => x.Email == "some@email.com")
// If we need more complex condition then use specification:
.Using(new UserNameContains("John"))
// Execute:
.List();
}
}
class UnitOfWork
{
public Repository<T> Over<T>()
{
// Get from DI container or injected field
return new Repository<T>();
}
}
class Repository<T>
{
public QueryWrapper<T> GetAll()
{
return new QueryWrapper<T>(Session.QueryOver<T>());
}
}
class QueryWrapper<T>
{
// Query from DB session. Init from constructor.
private IQueryOver<T> _query;
public QueryWrapper<T> Where(Expression<Func<T, bool>> expression)
{
_query = _query.Where(expression);
return this;
}
public QueryWrapper<T> Using(Specification<T> spec)
{
var spec = new TSpec();
_query = spec.Apply(_query);
return this;
}
public IEnumerable<T> List()
{
return return _query.List();
}
}
abstract class Specification<T>
{
public abstract IQueryOver<T> Apply(IQueryOver<T> query);
}
class UserNameContains : Specification<User>
{
// Init from constructor:
private string _name;
public override IQueryOver<User> Apply(IQueryOver<User> query)
{
return /* apply filter condition here */;
}
}因此,我们得到了这样的好处:
QueryWrapper以支持其他方法,如OrderBy等。请你指出我的方法的漏洞,或者提供你对这个问题的看法?此外,链接到现有的文章将是很好的。
发布于 2013-03-01 14:43:18
我的建议是将体系结构降到最低限度,并为自己证明每个添加的层和抽象的好处。最小的GetAll实现是:
Session.Query<User>();如果您有将被重用的限制,则可以将它们添加为扩展方法。如果您的可重用代码变得显而易见,那么重构到扩展方法就足够简单了。即使这样,对于简单的情况,如果您只是包装Lambda表达式,那么重构通常也没有什么好处,如本例所示。
public static IQueryable<User> UserNameContains(this IQueryable<User> queryable, string text)
{
return queryable.Where(u => u.UserNameContains(text));
}我不认为存储库模式非常有用,但它可以是组织代码的合理方法。但是我真的不喜欢通用存储库模式,因为它强制每个类规则一个存储库。如果我使用存储库,我喜欢对与根对象相关的查询进行分组(如Project、ProjectStatus等)。此外,在通用存储库中提供Get或GetAll方法没有好处,因为ISession已经提供了这些方法。
至于可测试性,查询的测试总是集成测试,在ASP.NET MVC中,我直接测试控制器或任何独立的查询方法。我在Windows窗体项目中使用存储库进行测试。
https://stackoverflow.com/questions/15117327
复制相似问题