出乎意料的IQueryable<> ForEach Iteration后的值

时间:2012-04-15 20:09:42

标签: vb.net linq-to-sql union

我很沮丧。

我正在使用VB.Net,Linq和DataContext。我的DataContext包含一个表'transactions'。

我首先声明一个IQueryable(Of transaction)并将其分配给任何东西。我在foreach循环中构建谓词并使用transactions.Where(谓词)为IQueryable分配一个值。如果我执行IQueryable.ToList(),我会在集合中获得许多项目。

但是,在循环的下一次迭代中,IQueryable.ToList()给了我0项。

这让我发疯了。我尝试使用VSQ10的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都会包含@variable迭代的参数(chosenCode)。当我运行查询时,我可能在生成的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

2 个答案:

答案 0 :(得分:1)

我不熟悉PredicateBuilder,但我认为你正在捕捉(关闭)chosenCode变量。

这意味着您的testRun3已填充该运行的selectedCode,但在下一次迭代中,testRun将填充 new selectedCode。

解决方案很简单,在groupQuery = groupQuery.ToList()之前执行Next

答案 1 :(得分:0)

我怀疑groupQuery.Union(vf.transactions.Where(codePredicate))可能正在生成不返回任何记录的sql。您可能希望在Management Studio中执行相同的查询。