Проецирование в KeyValuePair через EF/Linq

Я пытаюсь загрузить список KeyValuePairs из запроса EF/Linq следующим образом:

return (from o in context.myTable 
select new KeyValuePair<int, string>(o.columnA, o.columnB)).ToList();

Моя проблема в том, что это приводит к ошибке

«В LINQ to Entities поддерживаются только конструкторы без параметров и инициализаторы».

Есть ли простой способ обойти это? Я знаю, что мог бы создать собственный класс для этого вместо использования KeyValuePair, но это похоже на изобретение велосипеда.


person GrandMasterFlush    schedule 25.06.2013    source источник
comment
Обсуждение агрегации как альтернативного варианта: social.msdn.microsoft.com/Forums/en-US/   -  person George Johnston    schedule 25.06.2013


Ответы (3)


Выберите из таблицы только столбец A и столбец B и переместите дальнейшую обработку в память:

return context.myTable
              .Select(o => new { o.columnA, o.columnB }) // only two fields
              .AsEnumerable() // to clients memory
              .Select(o => new KeyValuePair<int, string>(o.columnA, o.columnB))
              .ToList();

Рассмотрите также возможность создания словаря, содержащего KeyValuePairs:

return context.myTable.ToDictionary(o => o.columnA, o => o.columnB).ToList();
person Sergey Berezovskiy    schedule 25.06.2013
comment
NB: причина, по которой это работает, заключается в том, что LINQ-to-Entities поддерживает только конструкторы без параметров, поэтому вы не можете использовать new KeyValuePair.... LINQ-to-Collections поддерживает конструкторы с параметрами. Когда вы вызываете AsEnumerable(), он оценивает запрос EF, а затем LINQ-to-Collections обрабатывает следующие .Select() - person Rory; 26.01.2015
comment
Как можно было бы реализовать ASYNC-версию этого? AsEnumerableAsync() метода нет. - person Zapnologica; 18.08.2015
comment
@Zapnologica — замените AsEnumerable() на ToListAsync(), затем заверните await в конец ToListAsync скобками и при необходимости добавьте .Select(o => new KeyValuePair<int, string>(o.columnA, o.columnB)).ToList(); Refactor. - person ttugates; 18.04.2018

Поскольку LINQ to Entities не поддерживает KeyValuePair, вы должны сначала перейти к LINQ to Object, используя AsEnumerable:

return context.myTable
              .AsEnumerable()
              .Select(new KeyValuePair<int, string>(o.columnA, o.columnB))
              .ToList();
person cuongle    schedule 25.06.2013
comment
хотя это работает, это неэффективно, так как загружает все столбцы из myTable - person Damian Green; 02.11.2015
comment
.Select(o=›new KeyValuePair‹int, string›(o.columnA, o.columnB)) - person vicky; 14.07.2021

Существует также альтернатива, когда вы хотите хранить несколько значений для одного ключа, существует то, что называется Поиск.

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

Вот несколько официальных документации.

Более того, поиск кажется намного быстрее, чем Dictionary ‹ TKey, List ‹ TValue > >.

person Bartosz    schedule 18.09.2017