Несколько критериев поиска в хранилище - PullRequest
2 голосов
/ 15 мая 2011

У меня есть вопрос о том, как реализовать несколько критериев для шаблона хранилища в ASP.net MVC.Представьте себе класс POCO в EF4

public class people
{ String Name {get;set;}
float Height {get;set;}
float Weight {get;set;}
int age {get;set;}
....
}

Если я создаю хранилище как IPeopleRepository, какие методы мне следует реализовать для поиска по нескольким критериям (например, возраст> 30, рост> 80).Эти критерии будут связаны со свойствами в классе, и некоторые входные данные могут быть нулевыми.Конечно, я могу написать метод, подобный

People SearchPeople (int age, float height.....) 

, но я должен судить, будет ли каждая переменная нулевой и добавляться к поисковым запросам.

Так что у вас есть какие-нибудь хорошие идеи покак реализовать эту функцию в EF?

Ответы [ 3 ]

7 голосов
/ 15 мая 2011

Звучит так, будто вы ищете что-то вроде шаблона Спецификация .

Здесь есть отличная статья, посвященная шаблону EF4 / POCO / Repository / Specification здесь .

Хотя мне нравится шаблон, я нахожу его немного излишним в простых сценариях.

В итоге я применил технику "каналов и фильтров" - в основном 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 строк.

4 голосов
/ 15 мая 2011

Во-первых, вам нужно подумать, действительно ли вам нужен метод поиска в репозитории.
Возможно, вы захотите выполнять прямые запросы, а не переносить их в репозиторий.

Однако, если вы считаете, что вам нуженметод поиска, чем вы, вероятно, будете использовать что-то вроде этого:

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();
}

Хотя вы не хотели этого делать, я не могу придумать лучшего решения.

1 голос
/ 15 мая 2011

В принципе, я думаю, что есть три варианта:

  1. Используйте шаблон спецификации и создайте столько отдельных спецификаций, сколько вам нужно, тогда вы можете более сложную спецификацию, комбинируя их через И / Или / Неоператоры.Вы можете посмотреть здесь пример http://code.google.com/p/linq-specifications/

  2. Создайте метод поиска, который принимает входной предикат, он является наиболее простым, поскольку он оставляет все критерии фильтрации работ для потребителей.

  3. Создайте метод поиска с другими критериями, затем создайте динамическое выражение Linq.Здесь есть PredicateBuilder: http://www.linqpad.net (ищите проект LinqKit).

...