Подтвердить что ты не робот

Присоединение в коллекции памяти и EntityFramework

Есть ли какой-либо механизм для создания 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 может быть довольно большим!

Resharper может реорганизовать, что для меня

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

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

4b9b3361

Ответ 1

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

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

Это вызовет запрос с оператором IN

Ответ 3

попробуйте следующее:

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 и т.д.)

Ответ 4

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

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