单表查询 (LINQ to DataSet)
语言集成查询 (LINQ) 查询适用于实现 IEnumerable<T> 接口或 IQueryable 接口的数据源。 DataTable 类不实现任何一个接口,所以如果要使用 DataTable 作为LINQ 查询的 From 子句中的源,则必须调用 AsEnumerable 方法。
下面的示例获取 SalesOrderHeader 表中的所有联机订单并将订单 ID、订单日期和订单编号输出到控制台。
' 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
// 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: {0} Order date: {1:d} Order number: {2}",
onlineOrder.SalesOrderID,
onlineOrder.OrderDate,
onlineOrder.SalesOrderNumber);
}
本地变量查询使用查询表达式进行初始化,该表达式通过应用标准查询运算符中的一个或多个查询运算符,或者在 LINQ to DataSet 的情况下应用特定于 DataSet 类的一个或多个运算符对一个或多个信息源进行运算。 前面示例中的查询表达式使用两个标准查询运算符:Where 和 Select。
Where 子句基于条件筛选序列,在本例中,OnlineOrderFlag 设置为 true。 Select 运算符分配并返回一个可枚举对象,该对象可捕获传递给运算符的参数。 在上面的示例中,创建了一个具有三个属性的匿名类型:SalesOrderID、OrderDate 和 SalesOrderNumber。 这三个属性的值设置为 SalesOrderHeader 表中的 SalesOrderID、OrderDate 和 SalesOrderNumber 列值。
然后,foreach 循环枚举由 Select 返回的可枚举对象,并生成查询结果。 由于查询是一种可以实现 IEnumerable<T> 的 Enumerable 类型,因此,查询的计算将推迟到使用 foreach 循环来循环访问查询变量之后进行。 推迟查询计算可使查询保持为可进行多次计算的值,每次计算都可能生成不同的结果。
Field 方法提供对 DataRow 列值的访问,而 SetField(前面的示例未演示)设置 DataRow 中的列值。 Field 方法和 SetField 方法都可以处理可以为 null 的类型,因此不必显式检查 null 值。 这两种方法也都是泛型方法,这意味着您不必强制转换返回类型。 您可以使用 DataRow 中预先存在的列访问器(例如 o["OrderDate"]),但是这样做要求您将返回对象强制转换为相应的类型。 如果列可以为 null,则必须使用 IsNull 方法检查值是否为 null。 有关更多信息,请参见 泛型 Field 和 SetField 方法 (LINQ to DataSet)。
请注意,Field 方法和 SetField 方法的泛型参数 T 中指定的数据类型必须与基础值的类型相匹配,否则将引发 InvalidCastException。 指定的列名称也必须与 DataSet 中的列名称相匹配,否则将引发 ArgumentException。 在这两种情况下,异常都是在执行查询期间的运行时数据枚举时引发的。