2012-03-26 84 views
0

这里是我当前的工作,查询:如何将条件添加到使用组的LINQ查询?

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的应纳税沿增加了一个过滤器的基本查询:

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

这是不是因为工作就是不承认ReplCost,只有SumOfReplValue,SumOfACV和SumOfReplCost。

有人可以告诉我,没有在两个步骤中执行查询,一种方法来添加此条件?如果没有办法做到这一点,将不胜感激:-)

在此先感谢!

回答

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的巨大好处。

+0

当一个组被创建时,投影类型也被改变,所以需要另一个变量而不是lsFooterRow – 2012-03-26 22:12:44

+0

@AdrianIftode好的,我只是把它扔在一起。我修好了。 – Devin 2012-03-26 22:15:21

+0

@Devin,谢谢,这对我来说非常有用。它不像我所希望的那样“整齐”,但是鉴于它的有效性,正如你所说的那样,这是一个很好的解决方案。这是一个伟大的“两步走”方法,可以在不牺牲性能的情况下提供灵活性,让人感到鼓舞! – 2012-03-27 20:22:33

0

如果你知道需要在数据库中执行了哪些SQL查询......你可以尝试http://www.linqpad.net/ 我觉得是非常方便的当u使用LINQ工作...

+0

我爱linqpad,谢谢! – 2012-03-27 20:49:06

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变量。

+0

我试过了,它不适合我,“原样”。我先试了一下,因为我喜欢它的简洁。当reportType!=“R”时,它作为一个空集返回,因为Devin的即插即用,我只是随之而去。我已经花了太多时间在这上面了。我感谢你的努力和时间。 – 2012-03-27 20:25:05