我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
感谢您的意见!我其实确实想要做一个旧的selectedCode和新的selectedCode的联合。另外,如果我执行'ToList()',恐怕查询将执行导致对SQL Server的不必要的调用。我错了吗? – ffrugone 2012-04-15 20:36:00
它可能是简化代码的人工产物,但它看起来像是一种非常复杂的导致1执行的方式。 – 2012-04-15 21:06:19
噢,伙计。我知道这么少。我不知道什么是1次执行。但是,我可以解释一下情况。 foreach的每次迭代都会生成插入到查询中的动态谓词。每个查询都是联合在一起的。然后在外部的foreach中,UNION的查询首先被分组,然后UNION与其他人一样。然后,再次进行过滤,最后再进行分组。 – ffrugone 2012-04-15 21:18:06