Language-Integrated LINQ 查询适用于实现 IEnumerable<T> 接口或 IQueryable<T> 接口的这些数据源。 该DataTable类不实现任一接口,因此,如果要在 AsEnumerable LINQ 查询的子句中使用DataTable作为源,则必须调用From该方法。
以下示例从 SalesOrderHeader 表中获取所有联机订单,并将订单 ID、订单日期和订单编号输出到控制台。
// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);
DataTable orders = ds.Tables["SalesOrderHeader"];
var query =
from order in orders.AsEnumerable()
where order.Field<bool>("OnlineOrderFlag") == true
select new
{
SalesOrderID = order.Field<int>("SalesOrderID"),
OrderDate = order.Field<DateTime>("OrderDate"),
SalesOrderNumber = order.Field<string>("SalesOrderNumber")
};
foreach (var onlineOrder in query)
{
Console.WriteLine($"Order ID: {onlineOrder.SalesOrderID} Order date: {onlineOrder.OrderDate:d} Order number: {onlineOrder.SalesOrderNumber}");
}
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)
Dim orders As DataTable = ds.Tables("SalesOrderHeader")
Dim query = _
From order In orders.AsEnumerable() _
Where order.Field(Of Boolean)("OnlineOrderFlag") = True _
Select New With { _
.SalesOrderID = order.Field(Of Integer)("SalesOrderID"), _
.OrderDate = order.Field(Of DateTime)("OrderDate"), _
.SalesOrderNumber = order.Field(Of String)("SalesOrderNumber") _
}
For Each onlineOrder In query
Console.Write("Order ID: " & onlineOrder.SalesOrderID)
Console.Write(" Order date: " & onlineOrder.OrderDate)
Console.WriteLine(" Order number: " & onlineOrder.SalesOrderNumber)
Next
局部变量 query 使用查询表达式进行初始化,该表达式通过应用一个或多个查询运算符来对一个或多个信息源执行操作,这些运算符可以是标准查询运算符,或者是在 LINQ to DataSet 中特定于 DataSet 类的查询运算符。 上一示例中的查询表达式使用两个标准查询运算符: Where 和 Select。
Where 子句根据条件筛选序列,其中 OnlineOrderFlag 设置为 true。 该 Select 运算符分配并返回一个可枚举对象,该对象捕获传递给运算符的参数。 在上面的示例中,使用三个属性创建匿名类型:SalesOrderID和OrderDateSalesOrderNumber。 这三个属性的值设置为 SalesOrderID 表中的 OrderDate、SalesOrderNumber 和 SalesOrderHeader 列的值。
然后 foreach 循环枚举 Select 返回的可枚举对象,并生成查询结果。 由于查询是一种Enumerable类型,并实现了IEnumerable<T>,因此查询的执行是延迟的,直到使用foreach循环遍历查询变量时才会进行。 延迟查询评估允许查询保留为可以多次评估的值,每次产生可能不同的结果。
该Field方法提供对DataRow的列值访问,而SetField(在上一个示例中未展示)则用于在DataRow中设置列值。 Field方法和SetField方法都处理可以为 null 的值类型,因此无需显式检查 null 值。 这两种方法也都是泛型方法,这意味着您不必强制转换返回类型。 您可以使用 DataRow 中预先存在的列访问器(例如 o["OrderDate"]),但是这样做要求您将返回对象强制转换为相应的类型。 如果列是可以为 null 的值类型,则必须使用方法 IsNull 检查该值是否为 null。 有关详细信息,请参阅 泛型字段和 SetField 方法。
请注意,T方法和Field方法的泛型参数SetField中指定的数据类型必须与基础值的类型匹配,否则将丢出InvalidCastException异常。 指定的列名必须与DataSet中的列名称匹配,否则将抛出ArgumentException。 在这两种情况下,异常都是在执行查询期间的运行时数据枚举时引发的。