2012-03-26 51 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