传递规范对象在存储库中是否过度
我问这个是因为,如果我们在FindCustomersCreatedToday等方法中传递规范对象,
class CustomerRepository
{
public List<Customer> FindCustomersCreatedToday(ISpecification ISCreatedToday)
{
List<Customer> customers= Load all customers from db;
List<Customer> newList=new List<>();
foreach(var customer in customers)
{
if(ISCreatedToday.SatisfiedBy(customer)
{
newList.Add(customer);
}
}
}
}
我在上面看到的大多数网站的实现,他们从数据库中获取所有实体并循环遍历它们并将它们传递给规范,但我不喜欢一次加载所有实体的想法然后创建一个新的筛选列表。
假设我有10000个客户,只有10个通过此标准。
通过规范是不是过度杀人?
答案 0 :(得分:2)
是的,如果你期待很多顾客,这肯定是一种矫枉过正。您可以使用规范实例中的信息生成适当的SQL / HQL或ICreteria(假设您使用NHibernate)。
public IList<Customer> FindCustomers(CreationDateRangeSpecification spec) {
ICriteria c = _nhibernateSession.CreateCriteria(typeof(Customer));
c.Add(Restrictions.Between("_creationDate", spec.Start, spec.End));
return c.List<Customer>();
}
这段代码比您发布的代码表现得差一些,但它仍然擅长捕获规范中的一些域信息。
使用规范时要记住的一件事是它是一个域概念。它属于域层,应该没有数据访问技术。获取数据的技术很重要,它们在域层中并不重要,它们属于数据访问层。在我看来,Expression<Func<Customer, bool>>
之类的内容对于域代码来说是“基础架构”。此外,基于Linq的规范倾向于要求域对象将其数据公开为有时会破坏其封装的属性。所以整个事情可能变成“Linq over Anemic Model”。
我强烈建议您阅读DDD book。它有一章专门讨论规范模式以及您正在处理的所有权衡。
答案 1 :(得分:2)
正如Ayende指出他的N-layer app review, LINQ是规范技术,如果你需要规范模式,你应该使用它。它具有可转换为SQL或HQL或任何其他查询语言的优点,因此可以在数据源上执行表达为Expression<Func<T, bool>>
的规范,而无需下载所有数据。