VB.Net与C#表达式树差异

时间:2014-06-25 21:02:12

标签: c# vb.net linq

我有一个LINQ查询,它在C#和VB.net中的文本非常相似。我正在尝试使用BLToolkit从Northwind数据库加载所有订单。这是我的Order课程。请注意,OrderDate DateTime是Nullable DateTime。

[TableName("Orders")]
public class Order : EntityBase<int>
{
    public int OrderID;
    public DateTime? OrderDate;
}

C#linq代码是:

from ord in Order
where ord.OrderDate == new DateTime(1997, 11, 14)
select ord.OrderID

VB linq代码是:

From order In db.Order _
Where order.OrderDate = #11/14/1997#
Select order.OrderID

执行时,C#代码生成此表达式树:

.Call System.Linq.Queryable.Select(
    .Call System.Linq.Queryable.Where(
        .Constant<BLToolkit.Data.Linq.Table`1[Data.Linq.Model.Northwind+Order]>(Table(Order)),
        '(.Lambda #Lambda1<System.Func`2[Data.Linq.Model.Northwind+Order,System.Boolean]>)),
    '(.Lambda #Lambda2<System.Func`2[Data.Linq.Model.Northwind+Order,System.Int32]>))

.Lambda #Lambda1<System.Func`2[Data.Linq.Model.Northwind+Order,System.Boolean]>(Data.Linq.Model.Northwind+Order $order) {
    $order.OrderDate == (System.Nullable`1[System.DateTime]).New System.DateTime(
        1997,
        11,
        14)
}

.Lambda #Lambda2<System.Func`2[Data.Linq.Model.Northwind+Order,System.Int32]>(Data.Linq.Model.Northwind+Order $order) {
    $order.OrderID
}

并且VB代码生成此表达式树:

.Call System.Linq.Queryable.Select(
    .Call System.Linq.Queryable.Where(
        .Constant<BLToolkit.Data.Linq.Table`1[Data.Linq.Model.Northwind+Order]>(Table(Order)),
        '(.Lambda #Lambda1<System.Func`2[Data.Linq.Model.Northwind+Order,System.Boolean]>)),
    '(.Lambda #Lambda2<System.Func`2[Data.Linq.Model.Northwind+Order,System.Int32]>))

.Lambda #Lambda1<System.Func`2[Data.Linq.Model.Northwind+Order,System.Boolean]>(Data.Linq.Model.Northwind+Order $order) {
    $order.OrderDate == (System.Nullable`1[System.DateTime]).New System.DateTime(
        1997,
        11,
        14) ?? False
}

.Lambda #Lambda2<System.Func`2[Data.Linq.Model.Northwind+Order,System.Int32]>(Data.Linq.Model.Northwind+Order $order) {
    $order.OrderID
}

为什么VB会在?? False上粘贴到OrderDate比较的末尾,具有什么意义呢?

Related issue report on BLToolkit

1 个答案:

答案 0 :(得分:4)

VB.NET处理与C#略有不同的可空类型,因此VB.NET可以向后兼容VB6。

Null的C#nullable是一个实际的Null,并在LINQ to SQL中进行转换。

一个VB nullable,Nothing有一个内部定义的默认值,因为VB6没有真正的“NULL”值。如果内部值是默认值,则可空字段的属性“.Value”返回Nothing,而LINQ直接使用内部值。

“?? False”是LINQ处理这个“Not really a Null”属性的方法,因此LINQ to Objects在使用Nullable类型时不会引人注目。这不会转换为SQL。

在使用Nullable类型的VB LINQ to SQL查询中,您必须将常规Where子句与“IsNot Nothing”或“field.HasValue”检查配对。这避免了LINQ隐式创建“is this null”检查。

示例:

Dim result = From row In Table _
             Where row.nullableField.HasValue AndAlso row.nullableField = someValue _
             Select row

或者

Dim result = From row In Table _
             Where row.nullableField IsNot Nothing AndAlso row.nullableField = anotherValue _
             Select row