2012-04-15 30 views
2

我flummoxed。意外的IQueryable <>值爲ForEach迭代後

我使用VB.Net,Linq和DataContext。我的DataContext包含一個表「交易」。

我首先聲明一個IQueryable(Of transaction)並將它分配給任何東西。我在foreach循環中構建謂詞並使用transactions.Where(謂詞)爲IQueryable賦值。如果我做了一個IQueryable.ToList(),我得到了集合中的許多項目。

但是,在循環的下一次迭代中,IQueryable.ToList()會給我0個項目。

這讓我瘋狂。我試圖用VS2010使用LINQ to SQL Debug Visualizer,(我用新引用重新編譯了2008版本),但沒有骰子 - 我看不到SQl生成或IQueryable內部有什麼。

下面的代碼:

Dim groupQuery As IQueryable(Of transaction) = Nothing 
For Each chosenCode As BillingCode In chosenGroup.BillingCodes 
    Dim testRun As List(Of transaction) = Nothing 
    If Not groupQuery Is Nothing Then 
     testRun = groupQuery.ToList() 
    End If 
    Dim codePredicate = PredicateBuilder.True(Of transaction)() 
    codePredicate = codePredicate.And(Function(i) i.code.Equals(chosenCode.Code)) 
    If Not chosenCode.Description Is Nothing Then codePredicate = codePredicate.And(Function(i) i.description.ToUpper().Contains(chosenCode.Description.ToUpper())) 
    If Not chosenCode.Insurance Is Nothing Then codePredicate = codePredicate.And(Function(i) i.v_patient.insname.ToUpper().Contains(chosenCode.Insurance.ToUpper())) 
    If Not chosenCode.PriceFloor Is Nothing Then codePredicate = codePredicate.And(Function(i) i.charge >= chosenCode.PriceFloor) 
    If Not chosenCode.PriceCeiling Is Nothing Then codePredicate = codePredicate.And(Function(i) i.charge <= chosenCode.PriceCeiling) 

    Dim testRun2 As List(Of transaction) = Nothing 
    Dim testRun3 As List(Of transaction) = Nothing 
    If groupQuery Is Nothing Then 
     groupQuery = vf.transactions.Where(codePredicate) 
    Else 
     testRun2 = groupQuery.ToList() 
     groupQuery = groupQuery.Union(vf.transactions.Where(codePredicate)) 
     testRun3 = groupQuery.ToList() 
    End If 
Next 

我會很感激的任何幫助。謝謝。

編輯:'testRun'變量僅供我調試代碼。我試圖做的是groupQuery = groupQuery.Union(QUERY FROM THIS ITERATION)而不執行查詢,直到我在代碼中轉換了幾次。對困惑感到抱歉。

回答編輯:我收到的兩個答案都有助於最終的解決方案。我最終都在每次迭代中調用ToList(),並使用Concat()而不是Union()。我發現每次運行Union()時,生成的SQL都會包含chosenCode該迭代的參數(@variable)。在運行查詢時,我可能會在生成的SQL中有10或20組參數(每次迭代爲chosenCode一組),但只​​有最後一組參數在運行時提供給SQL Server。不要問我爲什麼。這甚至沒有被證明,只是通過實驗得出的結論。一旦我明白了這一點,我無法弄清楚如何讓所有的參數通過。所以,我放棄了並且在chosenCode的每次迭代中將查詢運行到SQL Server。我仍然想知道如何在不完成構建之前運行查詢。

而不是在IQueryable上工作,我使用強類型List(Of transaction)來存儲ToList()的結果。然後我在我的代碼的其餘部分使用Linq to Objects來處理這個列表。

我還發現,使用Union()會在生成的SQL中生成UNION語句,但這並沒有給我預期的結果。因此,我使用了Concat(),它在生成的SQL中生成了一條UNION ALL語句,這正好給了我後面的內容。

謝謝,給大家的幫助。下面的代碼:

For Each chosenGroup As BillingGroup In chosenGroups 
     Dim groupResults As List(Of transaction) = Nothing 
     For Each chosenCode As BillingCode In chosenGroup.BillingCodes 

      Dim codePredicate = PredicateBuilder.True(Of transaction)() 
      codePredicate = codePredicate.And(Function(i) i.code.Equals(chosenCode.Code)) 
      If Not chosenCode.Description Is Nothing Then codePredicate = codePredicate.And(Function(i) i.description.ToUpper().Contains(chosenCode.Description.ToUpper())) 
      If Not chosenCode.Insurance Is Nothing Then codePredicate = codePredicate.And(Function(i) i.v_patient.insname.ToUpper().Contains(chosenCode.Insurance.ToUpper())) 
      If Not chosenCode.PriceFloor Is Nothing Then codePredicate = codePredicate.And(Function(i) i.charge >= chosenCode.PriceFloor) 
      If Not chosenCode.PriceCeiling Is Nothing Then codePredicate = codePredicate.And(Function(i) i.charge <= chosenCode.PriceCeiling) 

      If groupResults Is Nothing Then 
       groupResults = vf.transactions.Where(codePredicate).ToList() 
      Else 
       groupResults.AddRange(vf.transactions.Where(codePredicate).ToList()) 
      End If 
     Next 

回答

1

我不熟悉PredicateBuilder但我認爲你正在捕獲(關閉在上方)chosenCode變量存在。

這意味着您的testRun3是充滿了運行的chosenCode,但在接下來的迭代中testRun充滿 chosenCode。

解決方案很簡單,在之前,然後Next

+0

感謝您的意見!我其實確實想要做一箇舊的selectedCode和新的selectedCode的聯合。另外,如果我執行'ToList()',恐怕查詢將執行導致對SQL Server的不必要的調用。我錯了嗎? – ffrugone 2012-04-15 20:36:00

+0

它可能是簡化代碼的人工產物,但它看起來像是一種非常複雜的導致1執行的方式。 – 2012-04-15 21:06:19

+0

噢,夥計。我知道這麼少。我不知道什麼是1次執行。但是,我可以解釋一下情況。 foreach的每次迭代都會生成插入到查詢中的動態謂詞。每個查詢都是聯合在一起的。然後在外部的foreach中,UNION的查詢首先被分組,然後UNION與其他人一樣。然後,再次進行過濾,最後再進行分組。 – ffrugone 2012-04-15 21:18:06

0

我懷疑groupQuery.Union(vf.transactions.Where(codePredicate))可能會產生不返回任何記錄的SQL。您可能想要在Management Studio中執行相同的查詢。

+0

優秀!我結束了嘗試,發現我需要使用'Concat()'(UNION和UNION ALL之間的SQL差異)。 – ffrugone 2012-04-20 06:31:04

相關問題