Подсчет при отображении на объект в подзапросе linq - PullRequest
1 голос
/ 15 июня 2019

У меня есть запрос Linq, использующий оператор let, из которого я получаю несколько подзапросов. На данный момент я делаю 3 подзапроса для получения подсчетов с использованием 3 идентичных объединений, и я надеюсь объединить их в один подзапрос всего одним объединением. У меня что-то вроде этого:

let TheFruits = (complex query).ToList(),

Counter1 = (from TheTable in MyDC.SomeTable

             join x in Thefruits on                                                                   
             TheTable.FruitID equals x.FruitID

             where x.Field1 == 1

             select x).Count(),

Counter2 = (from TheTable in MyDC.SomeTable

             join x in Thefruits on                                                                   
             TheTable.FruitID equals x.FruitID

             where x.Field2 == 2

             select x).Count(),

Counter3 = (from TheTable in MyDC.SomeTable

             join x in Thefruits on                                                                   
             TheTable.FruitID equals x.FruitID

             where x.Field3 == 3

             select x).Count(),

Чтобы заменить 3 соединения, я хочу написать что-то вроде этого, но я не получаю методы расширения в свойствах объекта:

let TheFruits = (complex query).ToList(),

TheCounterObject = (from TheTable in MyDC.SomeTable

                    join x in Thefruits on                                                                   
                    TheTable.FruitID equals x.FruitID

                    select new CounterObject()
                    {
                        Count1 = x.Where....Count(),
                        Count2 = x.Where....Count(),
                        Count3 = x.Where....Count(),

                        //not getting .Where extension

                    }).Single()

Проблема в том, что я не получаю методы расширения, только столбцы таблицы. В приведенном мною простом примере предложение .Where соответствует только одному условию, но в моем фактическом подзапросе присутствуют DateTimes и другие условия.

Как запустить подсчет на этапе сопоставления объектов?

Редактировать

Еще немного поработав, у меня теперь есть следующее:

let TheFruits = (complex query).ToList(),

TheCounterObject = (from TheTable in MyDC.SomeTable

                    join x in TheFruits on                                                                   
                    TheTable.FruitID equals x.FruitID

                    into TheSubFruits

                    select new CounterObject()
                    {
                        Count1 = TheSubFruits.Where(x.FruitID == TheTable.FruitID && other conditions).Count(),

                        Count2 = TheSubFruits.Where(x.FruitID == TheTable.FruitID && other conditions).Count(),

                        Count3 = TheSubFruits.Where(x.FruitID == TheTable.FruitID && other conditions).Count()
                    }).First()

Проблема в том, что счет неправильный, и если я использую .Single () вместо .First (), я также получаю ошибку «Последовательность содержит более одного элемента».

Почему этот подзапрос не возвращает те же значения, что и 3 подзапроса? Что мне нужно изменить?

1 Ответ

0 голосов
/ 15 июня 2019

Вы не получаете расширение .Where на x, потому что в этот момент x больше не перечисляется.x представляет каждый отдельный фрукт, но вы хотите применить .Where ко всем из них.Чтобы сделать это, вы можете выполнить объединение, а затем выполнить подсчет, как я показываю при редактировании.

Редактировать

Если вам нужны отдельные подсчеты для отдельных условий, я бы предложил что-то вроде этого:

var joined = (from TheTable in MyDC.SomeTable
              join x in Thefruits on                                   
              TheTable.FruitID equals x.FruitID
              select x).ToList();

var count1 = joined.Where(...).Count();
var count2 = joined.Where(...).Count();
var count3 = joined.Where(...).Count();

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

Edit # 2

Подумав об этом немного больше, вы можете сделать что-то очень похожее на то, что вы показали вВаш второй пример и объедините его с совокупностью, чтобы получить желаемый результат.

var counts = (from TheTable in MyDC.SomeTable
              join x in Thefruits on                                   
              TheTable.FruitID equals x.FruitID
              select new {
                  // Calculate whether this object be included in each count 
                  Count1 = x.FruitId == 1 ? 1 : 0,
                  Count2 = x.FruitId == 2 ? 1 : 0,
                  Count3 = x.FruitId == 3 ? 1 : 0
              }).Aggregate((acc, i) => new {
                  Count1 = acc.Count1 + i.Count1,
                  Count2 = acc.Count2 + i.Count2,
                  Count3 = acc.Count3 + i.Count3
              });

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

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