在linq子查询中映射到对象时进行计数

时间:2019-06-15 16:42:29

标签: c# linq linq-to-sql

我有一个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 :(得分:0)

您在.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();

这将允许您具有多个条件,条件甚至可以重叠并在需要时计数相同的对象。它与您最初拥有的资源非常相似,但是只执行一次连接。

编辑#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
              });

这是其中一个工作的example,具有伪数据类,现在具有联接。这可能与您要查找的内容最接近,因为它仅执行一次连接,将对象视为进行映射的对象,并允许多个复杂条件。