如何向使用组的LINQ查询添加条件?

时间:2012-03-26 21:45:42

标签: linq entity-framework-4

这是我当前的,有效的查询:

var lsFooterRow = from i in _context.Inventory
                  where i.ClaimId == claimID
                  && i.Taxable == false
                  group i by new { i.ClaimId }
                      into grp
                      select new
                      {
                          SumOfReplValue = grp.Sum(i => i.Price),
                          SumOfACV = grp.Sum(i => i.ACV),
                          SumOfReplCost = grp.Sum(i => i.ReplacementCost)
                      };

我想添加它,使其具有条件性,就是这样,以便它添加一个过滤器到基本查询以及ClaimID和Taxable:

if (reportType == "R")
            lsFooterRow = lsFooterRow.Where(i => i.ReplCost > 0);

这不起作用,因为它不识别ReplCost,只识别SumOfReplValue,SumOfACV和SumOfReplCost。

有人可以告诉我,无需分两步查询,添加此条件的方法吗?如果没有办法,我们将非常感谢两步法: - )

提前致谢!

3 个答案:

答案 0 :(得分:3)

如果我理解正确,你应该将初始查询分成多个部分。

  var lsFooterRow = from i in _context.Inventory
              where i.ClaimId == claimID
              && i.Taxable == false
              select i;

  // conditional where
  if (reportType == "R")
        lsFooterRow = lsFooterRow.Where(i => i.ReplacementCost > 0);


  var aggregateFooterRow =  from i in lsFooterRow
         group i by new { i.ClaimId }
                  into grp
                  select new
                  {
                      SumOfReplValue = grp.Sum(i => i.Price),
                      SumOfACV = grp.Sum(i => i.ACV),
                      SumOfReplCost = grp.Sum(i => i.ReplacementCost)
                  };

通过这种方式,您可以在汇总之前过滤重置成本,这听起来就像您想要做的那样。

您确实表达了对两部分查询的担忧,但这不应该构成问题。关于这一点的好处是,在您枚举查询的最终版本之前,它不会编写和执行sql。实体框架引擎非常智能,可以简单地将第二个作为另一个条件添加到SQL中的最终where语句中。这意味着你的会员将整齐地成为查询的一部分,而不是事后的想法。您可以分解查询并根据需要添加条件事项。

将查询分解为多个部分并有条件地构成查询的能力是LINQ对SQL的巨大好处。

答案 1 :(得分:1)

@Devin的回答可能是最干净的,并且对于linq的延迟执行以及2步不是两个查询的方式提出了一个重要的迂腐点。 那就是,如果你想在一个查询中做到这一点,你可以编写第一个查询来包含额外条件,如下所示:

var lsFooterRow = from i in _context.Inventory
                  where i.ClaimId == claimID
                  && i.Taxable == false
                  && (i.ReplacementCost > 0 || reportType != "R")
                  group i by new { i.ClaimId }
                      into grp
                      select new
                      {
                          SumOfReplValue = grp.Sum(i => i.Price),
                          SumOfACV = grp.Sum(i => i.ACV),
                          SumOfReplCost = grp.Sum(i => i.ReplacementCost)
                      };

修改 嗯,我能想到的唯一一件事就是让这个失败,而@Devin的工作,就是你要在这个声明和lsFooterRow的实际枚举发生之间改变reportType的值。如果发生这种情况,你可以随时直接.ToList()。或者,资源密集程度较低,将reportType复制到永不更改的临时变量,并在查询中引用该变量。

string _reportType = reportType //only set here, nowhere else
var lsFooterRow = from i in _context.Inventory
                  where i.ClaimId == claimID
                  && i.Taxable == false
                  && (i.ReplacementCost > 0 || _reportType != "R")
                  group i by new { i.ClaimId }
                      into grp
                      select new
                      {
                          SumOfReplValue = grp.Sum(i => i.Price),
                          SumOfACV = grp.Sum(i => i.ACV),
                          SumOfReplCost = grp.Sum(i => i.ReplacementCost)
                      };

但是现在它不再那么干净,并且在闭包内不必要地捕获_reportType变量。

答案 2 :(得分:0)

如果你知道在DB上需要执行什么SQL查询...你可以尝试http://www.linqpad.net/ 当你使用linq时我觉得非常方便...