存储库中的多个搜索条件

时间:2011-05-15 04:47:43

标签: asp.net-mvc entity-framework search repository

我有一个关于如何在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中实现此功能有任何好的想法吗?

3 个答案:

答案 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)

基本上我认为有三种选择:

  1. 使用规范模式并根据需要创建任意数量的单一规范,然后通过And / Or / Not运算符组合它们可以实现更复杂的规范。您可以在此处查看示例http://code.google.com/p/linq-specifications/

  2. 创建一个接受输入谓词的搜索方法,这是最简单的一个,因为它将所有条件过滤都留给了消费者。

  3. 使用不同的条件创建搜索方法,然后构建动态Linq表达式。这里有一个PredicateBuilder:http://www.linqpad.net(寻找LinqKit项目)。