我有一个关于如何在ASP.net MVC中为存储库模式实现多个条件的问题。想象一下EF4中的POCO课程
public class people
{ String Name {get;set;}
float Height {get;set;}
float Weight {get;set;}
int age {get;set;}
....
}
如果我将库建立为IPeopleRepository
,我应该为多标准搜索实现哪种方法(例如Age> 30,Height> 80)。这些标准与类中的属性有关,一些输入可能为null。当然我可以写一个像
People SearchPeople (int age, float height.....)
但我必须判断每个变量是否为null并附加到搜索查询中。
那么您对如何在EF中实现此功能有任何好的想法吗?
答案 0 :(得分:7)
听起来你正在寻找类似规范模式的东西。
有一篇很好的文章涉及EF4 / POCO / Repository / Specification模式here。
虽然我喜欢这种模式,但在简单的场景中我发现它有点过分。
我最终使用了“管道和过滤器”技术 - 基本上IQueryable<T>
对象的扩展方法,使您的存储库代码流畅。
但是对于搜索条件,我很想让消费代码提供谓词,那么你不必担心参数。
所以定义是这样的:
public People SearchPeople(Expression<Func<People,bool>> predicate)
{
return _context.People.SingleOrDefault(predicate);
}
然后代码只提供谓词。
var person = _repository.SearchPeople(p => p.Age > 30 && p.Height > 80);
有些人不喜欢这种技术,因为它给消费者带来了太大的“力量”,因为他们可能提供像p.Id > 0
这样的谓词并返回数据库中的所有行。
要抵消这种情况,请为maxRows提供可选参数。如果未提供,则默认为100行。
答案 1 :(得分:4)
首先,您需要考虑是否确实需要存储库搜索方法
您可能希望直接查询而不是将它们包装到存储库。
但是,如果您认为需要搜索方法,则可能会使用以下内容:
private People SearchPeople(int? age, float? height)
{
var baseQuery = db.People;
if (age != null)
baseQuery = baseQuery.Where(arg => arg.Age > age);
if (height != null)
baseQuery = baseQuery.Where(arg => arg.Height > height);
return baseQuery.ToList();
}
虽然你不想这样做,但我想不出更好的解决方案。
答案 2 :(得分:1)
基本上我认为有三种选择:
使用规范模式并根据需要创建任意数量的单一规范,然后通过And / Or / Not运算符组合它们可以实现更复杂的规范。您可以在此处查看示例http://code.google.com/p/linq-specifications/
创建一个接受输入谓词的搜索方法,这是最简单的一个,因为它将所有条件过滤都留给了消费者。
使用不同的条件创建搜索方法,然后构建动态Linq表达式。这里有一个PredicateBuilder:http://www.linqpad.net(寻找LinqKit项目)。