Сначала код EF: как выполнить поиск по нескольким таблицам / сущностям?

#c# #sql #entity-framework

#c# #sql #entity-framework

Вопрос:

У меня есть 4 несвязанных объекта, и я хотел бы запросить у них определенное ключевое слово. У каждого объекта было последнее измененное поле, и я хотел бы вернуть 50 лучших результатов поиска по 4 таблицам, упорядоченным по последнему измененному полю. Возможно ли это вообще?

В прошлом я использовал представление для выполнения подобных действий … но я не понимаю, как сначала добиться этого с помощью кода EF.

Ответ №1:

Вам нужно будет:

  • Поиск в каждой таблице
  • Преобразуйте результаты в общий тип
  • Объединить результаты
  • Сортировать / выбирать из этого объединенного списка
  • Возьмите первые 50 результатов.

Первые два можно выполнить с помощью LINQ to Entities, а последние три — с помощью LINQ to Objects .

РЕДАКТИРОВАТЬ Этот подход будет выглядеть примерно так:

 var resA = from a in db.A
           where ConditionA(a)
           select MakeSharedFromA(a);
var resB = from b in db.B
           where ConditionB(b)
           select MakeSharedFromB(b);
var resC = from c in db.C
           where ConditionC(c)
           select MakeSharedFromC(c);
var resD = from d in db.D
           where ConditionD(d)
           select MakeSharedFromD(d);

var merged = resA.AsEnumerable().Take(50)
                 .Concat(resB.AsEnumerable().Take(50))
                 .Concat(resC.AsEnumerable().Take(50))
                 .Concat(resD.AsEnumerable().Take(50));

var res = merged.Sort(x => x.SortField).Take(50);
 

Если каждый из MakeSharedFromX методов может быть заменен на лямбда-выражение (для получения дерева выражений), которое ограничено операторами и функциями, которые поддерживает LINQ to Entities, то отбросьте AsEnumerable Take вызовы and с шага конкатенации, и все это может быть выполнено на стороне сервера.

Комментарии:

1. Это заставит меня выбрать не менее 50 записей из каждой таблицы. Есть ли способ поместить все это в LINQ to Entities (= LINQ to SQL)?

2. @KeesC.Bakker Только в том случае, если коллекции сущностей имеют один и тот же тип, в противном случае вы пытаетесь объединить яблоки и апельсины. Возможно, стоит попробовать с шагом проекции / преобразования в L2E, а затем посмотреть, поддерживает ли L2E Concat оператор. Я расширю A…

3. Я создал для запросов (в них orderby и Take(50)). Каждый запрос выбирает запись в классе ResultRecord. Когда я делаю var searches = from s in setA.Concat(setB).Concat(setC).Concat(setD) orderby s.Modified select s; , все работает идеально! Не знаю о последствиях для производительности.

4. Я бы, вероятно, согласился с вашей интуицией в отношении сохраненной процедуры или представления. Похоже, это та область, где KISS будет применяться, а не пытаться заставить EF делать что-то, в чем он не так хорош, и у большинства ORM в целом будут проблемы с тем, что вы пытаетесь сделать.

5. Это решение все еще действует для EF 6 или есть какой-нибудь лучший способ?