Соединение между в памяти коллекции и EntityFramework - PullRequest
15 голосов
/ 01 июля 2011

Существует ли какой-либо механизм для выполнения JOIN между коллекцией в памяти и структурой сущностей при сохранении порядка.

Я пытаюсь

var itemsToAdd = 
  myInMemoryList.Join(efRepo.All(), listitem => listitem.RECORD_NUMBER,
  efRepoItem => efRepoItem.RECORD_NUMBER, (left, right) => right);

, что дает мне довольно любопытное название «Этот метод поддерживает инфраструктуру LINQ to Entities и не предназначен для использования непосредственно из вашего кода». ошибка.

Теперь, конечно, я могу сделать это итеративно с чем-то вроде

        foreach (var item in myInMemoryList)
        {
            var ho = efRepo.Where(h => h.RECORD_NUMBER == item.RECORD_NUMBER).FirstOrDefault();
            tmp.Add(ho);
        }

но это запрос N + 1. Что неприятно, поскольку myInMemoryList может быть довольно большим!

Решарпер может рефакторинг, что для меня

        tmp = (from TypeOfItemInTheList item in myInMemoryList 
           select efRepo.Where(h => h.RECORD_NUMBER == item.RECORD_NUMBER)
           .FirstOrDefault());

, который я подозреваю, все еще выполняет N + 1 запросов. Так что любые идеи для лучшего подхода к получению сущностей ef, которые (в ключевом поле) соответствуют коллекции в памяти. Результирующий набор должен быть в том же порядке, что и коллекция в памяти.

Ответы [ 4 ]

17 голосов
/ 01 июля 2011

Нет, вы не можете объединить коллекцию в памяти с набором результатов базы данных, не загрузив весь набор результатов в память и не выполнив соединение с linq-to-objects.Попробуйте использовать содержимое вместо соединения:

var myNumbers = myInMemoryList.Select(i => i.RECORD_NUMBER);
var itemsToAdd = efRepo.Where(e => myNumbers.Contains(e.RECORD_NUMBER));

Это сгенерирует запрос с оператором IN

3 голосов
/ 05 января 2014

Вы можете прочитать, как вы можете сделать это с помощью PredicateBuilder из LINQKit или Хранимых процедур в моем блоге.

http://kalcik.net/2014/01/05/joining-data-in-memory-with-data-in-database-table/

2 голосов
/ 01 июля 2011

попробуйте это:

var list = (from n in efRepo
           where myInMemoryList.Select(m=>m.RECORD_NUMBER).Contains(n.RECORD_NUMBER)
           select n).ToList();

Contains будет преобразовано в оператор IN в SQL (только если ваш член RECORD_NUMBER имеет примитивный тип, например int, string, Guid и т. Д.)

0 голосов
/ 01 июля 2011

Как насчет загрузки всего efRepo?Я имею в виду что-то вроде этого (ToArray ()):

var itemsToAdd = myInMemoryList.Join(
    efRepo.ToArray(),
    listitem => listitem.RECORD_NUMBER, efRepoItem => efRepoItem.RECORD_NUMBER, (left, right) => right);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...