2012-04-15 47 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

相关问题