Сложный запрос типа «многие ко многим» заставил меня застрять - PullRequest
0 голосов
/ 14 апреля 2011

Итак, я в Linq-To-Entities с проектом asp.net mvc.

Я всегда немного озадачен таким запросом.

Моя схема:

ProductTag
+TagName
+<<ProductNames>>//Many-to-many relationship

ProductName
+FullName
+<<Tag>>//Many-to-many relationship

PurchaseRecord
+Amount
+<<ProductName>>//one productname can be linked to Many purchase records.

Мне нужно получить сумму всех покупок для данного тега.

Это то, что я пробовал.

ProductTag thetag//could be some tag

decimal total = myentities.PurchaseRecords
                    .Where(x => thetag.ProductNames.Any
                         (a => a.FullName == x.ProductName.FullName))
                         .Sum(s => s.Amount);

Я пытался изменить пару вещей, пытался использовать Contains, но я знаю, что где-то в корне ошибаюсь.

Я продолжаю получать:

Невозможно создать постоянное значение типа «ProductName». В этом контексте поддерживаются только примитивные типы (такие как Int32, String и Guid).

Обновление Так что с помощью @ Alexandre Brisebois ниже она работала просто так:

var total= item.ProductNames.SelectMany(x => x.PurchaseRecords)
                                             .Sum(s => s.Amount);

Ответы [ 2 ]

1 голос
/ 14 апреля 2011

Когда вы получаете ошибку такого рода, вам нужно выполнить все оценки вне запроса linq и передать значения в виде переменных.

проблема с вашим запросом состоит в том, что thetag.ProductNames.Any() находится вне контекста.

Эта оценка не преобразуется в SQL, поскольку она не является строкой / guid или int.

Вам потребуется запросить этот объект в запросе и выполнить оценку на основе этого объекта.

Я не уверен, что это было ясно.

Вам нужно будет сделать что-то вроде

var query1 = (from x in tags where x.tagID = id select x.ProductNames)
                                                          .SelectMany(...)

Выбор многих из-за того, что вы выбираете коллекцию ProductNames инужно вернуть его как плоский набор / коллекцию, чтобы вы могли сделать .Any() для него в следующем запросе.

Затем используйте это и выполните query1.Any(logic)

decimal total = myentities.PurchaseRecords.
                           Where(x => query1.Any
                                (a => a.FullName == x.ProductName.FullName))
                                .Sum(s => s.Amount); 

Делая это, вы останетесь в linq для сущности и не преобразуете в linq для объектов.

ForEach не вариант, так как он будет выполнять итерацию по коллекции.

0 голосов
/ 14 апреля 2011

Вы можете использовать метод AsEnumerable для выполнения определенных частей запроса в C #, а не на сервере SQL. это обычно требуется, когда у вас есть часть данных в памяти (коллекция объектов), поэтому использовать их в запросе нелегко. Вы должны выполнить часть выполнения запроса на стороне .net. для вашей проблемы плз попробуйте

decimal total = myentities.PurchaseRecords.AsEnumerable()
                    .Where(x => thetag.ProductNames.Any
                         (a => a.FullName == x.ProductName.FullName))
                         .Sum(s => s.Amount);

Пожалуйста, перейдите по этой ссылке , чтобы узнать больше о AsEnumerable

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...