Ошибка соединения | Невозможно создать постоянное значение типа только примитив - PullRequest
0 голосов
/ 28 августа 2018

Очень новый с LINQ здесь.

У меня есть следующие данные в моей таблице (Таблица A):

ID  Name      SubmissionNo
1   Jim       A-1
2   Andy      A-2
3   Rick      A-2
4   Mary      A-3
5   Zim       A-4
6   Loren     A-1

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

Вот мое решение (контекст - это контекст базы данных):

var duplicates = (from tbl in Context.TableA.AsNoTracking()
                  group tbl by tbl.SubmissionNo into grp
                  select new { count = grp.Count(), submissionNo = grp.Key})
                 .Where(x => x.count > 1)
                 .OrderBy(y => y.submissionNo).ToList();

Переменная дубликатов содержит запись:

count  submissionNo
2      A-1
2      A-2

Затем я пишу основной запрос, который позволит мне получить все записи из Таблицы A, в которой есть дублирующая отправка. Нет

var myList = (from tbl in Context.TableA.AsNoTracking()
              join dup in duplicates on tbl.SubmissionNo equals dup.submissionNo
              select new 
              { 
                ID = tbl.ID, 
                Name = tbl.Name, 
                SubmissionNo = tbl.SubmissionNo 
              })
              .ToList();

Я получаю сообщение об ошибке для запроса myList с

Невозможно создать постоянное значение типа «Анонимный тип». В этом контексте поддерживаются только примитивные типы или типы перечисления.

Я думаю, что должен быть лучший способ сделать это, как показано в Таблице A выше, мне практически нужны следующие результаты:

ID  Name      SubmissionNo
1   Jim       A-1
2   Andy      A-2
3   Rick      A-2
6   Loren     A-1

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

Ваш первый запрос, слегка измененный, содержит всю необходимую информацию:

var myList  = from tbl in Context.TableA.AsNoTracking()
              group tbl by tbl.SubmissionNo into grp
              where grp.Count() > 1
              from item in grp
              select new
              { 
                  count = grp.Count(),
                  submissionNo = grp.Key,
                  item.Name,
              );

Шаблон group into grp - from item in grp является часто используемым шаблоном запроса для группировки элементов, а затем снова сглаживает группу, сохраняя при этом связь с данными группы (например, Count() и Key).

Теперь вам больше не нужно объединение, и исключение не происходит. Кстати, исключение говорит вам, что EF может обрабатывать только объединения с коллекциями примитивных типов (int и т. Д.), Потому что оно должно переводить все выражение в SQL. Для богатых объектов просто нет перевода, таких как TableA.

Кстати, запрос можно улучшить, удалив повторяющиеся Count():

var myList  = from tbl in Context.TableA.AsNoTracking()
              group tbl by tbl.SubmissionNo into grp
              let count = grp.Count()
              where count > 1
              from item in grp
              select new
              { 
                  count = count,
                  submissionNo = grp.Key,
                  item.Name,
              );

Это создаст более эффективный оператор SQL, содержащий один COUNT вместо двух.

0 голосов
/ 28 августа 2018

Поскольку Entity Framework не поддерживает объединение коллекций объектов в памяти с коллекциями баз данных, общий обходной путь для этого заключается в фильтрации с использованием Contains.

Во-первых, вам нужно получить идентификаторы для фильтрации:

var duplicates = (from tbl in Context.TableA.AsNoTracking()
                  group tbl by tbl.SubmissionNo into grp
                  select new { count = grp.Count(), submissionNo = grp.Key})
                 .Where(x => x.count > 1)
                 .OrderBy(y => y.submissionNo)
                 .ToList();
var duplicateIds = duplicates.Select(x => x.submissionNo).ToList();

А затем измените ваш запрос на выполнение WHERE...IN вместо JOIN:

var myList = (from tbl in Context.TableA.AsNoTracking()
              where duplicateIDs.Contains(tbl.SubmissionNo)
              select new 
              { 
                ID = tbl.ID, 
                Name = tbl.Name, 
                SubmissionNo = tbl.SubmissionNo 
              })
              .ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...