C# 2008 学习笔记 - LINQ to ADO.NET(二)- LINQ to DataSet
Posted on 2008-02-22 14:32 sunrack 阅读(2750) 评论(1) 编辑 收藏 举报
一、获取标准DataSet数据的三种方法
a. 下标
b. Data table readers
c. 强类型数据成员
LINQ to DataSet 提供了另外一种访问方式,但是,标准的DataSet(以及相关的DataTable 和DataView) 并不能直接支持LINQ
会出现编译错误,提示DataTable并未提供“query pattern implementation.”。和其他没有实现IEnumerable<T>的对象一样,需要将ADO.NET对象转化为IEnumerable<T>兼容类型。
二、DataSet 扩展
System.Data.DataSetExtensions.dll 对 System.Data 进行了很多扩展。其中最重要的扩展是DataTableExtensions 、DataRowExtensions 和 TypedTableBaseExtensions(用于扩展类型化的DataSet)。其他的扩展都不需要再代码中使用。
三、获取 LINQ 兼容的 DataTable
Visual studio 2008 项目会自动添加对 System.Core.dll 和 System.Data.DataSetExtensions.dll 的引用。
可以使用 DataTableExtensions 中定义的 AsEnumerable() 方法把 DataTable 转换为支持LINQ。返回类型是 EnumerableRowCollection, 是 DataRows. 的集合, 这样就可以访问每一行了
由于 EnumerableRowCollection 实现了 IEnumerable<T>,所以,又可以写为:
注意, 这里并没有定义LINQ查询,只是对象 enumData 现在可以用于创建LINQ查询表达式了。
一般不需要定义 EnumerableRowCollection 对象 来保存 AsEnumerable() 的返回值,而是在查询表达式中直接调用AsEnumerable()。
四、DataRowExtensions.Field<T>()
前面的示例都使用了下标和强制类型转换,如果数据类型不一致,可能会导致运行时错误。可以使用 DataRow 的 Field<T>() 扩展方法
这可以将LINQ查询结果集用在数据绑定中
a. 下标
b. Data table readers
c. 强类型数据成员
static void PrintDataWithIndxers(DataTable dt)
{
// Print the DataTable.
for (int curRow = 0; curRow < dt.Rows.Count; curRow++)
{
for (int curCol = 0; curCol < dt.Columns.Count; curCol++)
{
Console.Write(dt.Rows[curRow][curCol].ToString() + "\t");
}
Console.WriteLine();
}
}
{
// Print the DataTable.
for (int curRow = 0; curRow < dt.Rows.Count; curRow++)
{
for (int curCol = 0; curCol < dt.Columns.Count; curCol++)
{
Console.Write(dt.Rows[curRow][curCol].ToString() + "\t");
}
Console.WriteLine();
}
}
static void PrintDataWithDataTableReader(DataTable dt)
{
// Get the DataTableReader type.
DataTableReader dtReader = dt.CreateDataReader();
while (dtReader.Read())
{
for (int i = 0; i < dtReader.FieldCount; i++)
{
Console.Write("{0}\t", dtReader.GetValue(i));
}
Console.WriteLine();
}
dtReader.Close();
}
{
// Get the DataTableReader type.
DataTableReader dtReader = dt.CreateDataReader();
while (dtReader.Read())
{
for (int i = 0; i < dtReader.FieldCount; i++)
{
Console.Write("{0}\t", dtReader.GetValue(i));
}
Console.WriteLine();
}
dtReader.Close();
}
static void AddRowWithTypedDataSet()
{
InventoryTableAdapter invDA = new InventoryTableAdapter();
AutoLotDataSet.InventoryDataTable inv = invDA.GetData();
inv.AddInventoryRow(999, "Ford", "Yellow", "Sal");
invDA.Update(inv);
}
{
InventoryTableAdapter invDA = new InventoryTableAdapter();
AutoLotDataSet.InventoryDataTable inv = invDA.GetData();
inv.AddInventoryRow(999, "Ford", "Yellow", "Sal");
invDA.Update(inv);
}
LINQ to DataSet 提供了另外一种访问方式,但是,标准的DataSet(以及相关的DataTable 和DataView) 并不能直接支持LINQ
static void LinqOverDataTable()
{
// Get a DataTable of data.
InventoryDALDisLayer dal = new InventoryDALDisLayer(
@"Data Source=(local)\SQLEXPRESS;" +
"Initial Catalog=AutoLot;Integrated Security=True");
DataTable data = dal.GetAllInventory();
// Get cars with CarID > 5?
var moreData = from c in data where (int)c["CarID"] > 5 select c;
}
{
// Get a DataTable of data.
InventoryDALDisLayer dal = new InventoryDALDisLayer(
@"Data Source=(local)\SQLEXPRESS;" +
"Initial Catalog=AutoLot;Integrated Security=True");
DataTable data = dal.GetAllInventory();
// Get cars with CarID > 5?
var moreData = from c in data where (int)c["CarID"] > 5 select c;
}
会出现编译错误,提示DataTable并未提供“query pattern implementation.”。和其他没有实现IEnumerable<T>的对象一样,需要将ADO.NET对象转化为IEnumerable<T>兼容类型。
二、DataSet 扩展
System.Data.DataSetExtensions.dll 对 System.Data 进行了很多扩展。其中最重要的扩展是DataTableExtensions 、DataRowExtensions 和 TypedTableBaseExtensions(用于扩展类型化的DataSet)。其他的扩展都不需要再代码中使用。
三、获取 LINQ 兼容的 DataTable
Visual studio 2008 项目会自动添加对 System.Core.dll 和 System.Data.DataSetExtensions.dll 的引用。
可以使用 DataTableExtensions 中定义的 AsEnumerable() 方法把 DataTable 转换为支持LINQ。返回类型是 EnumerableRowCollection, 是 DataRows. 的集合, 这样就可以访问每一行了
static void PrintAllCarIDs(DataTable data)
{
// Get enumerable version of DataTable.
EnumerableRowCollection enumData = data.AsEnumerable();
// Print the car ID values.
foreach (DataRow r in enumData)
Console.WriteLine("Car ID = {0}", r["CarID"]);
}
{
// Get enumerable version of DataTable.
EnumerableRowCollection enumData = data.AsEnumerable();
// Print the car ID values.
foreach (DataRow r in enumData)
Console.WriteLine("Car ID = {0}", r["CarID"]);
}
由于 EnumerableRowCollection 实现了 IEnumerable<T>,所以,又可以写为:
// Store return value as IEnumerable<T>.
IEnumerable<DataRow> enumData = data.AsEnumerable();
// Store return value implicitly.
var enumData = data.AsEnumerable();
IEnumerable<DataRow> enumData = data.AsEnumerable();
// Store return value implicitly.
var enumData = data.AsEnumerable();
注意, 这里并没有定义LINQ查询,只是对象 enumData 现在可以用于创建LINQ查询表达式了。
一般不需要定义 EnumerableRowCollection 对象 来保存 AsEnumerable() 的返回值,而是在查询表达式中直接调用AsEnumerable()。
static void ApplyLinqQuery(DataTable data)
{
// Project a new result set containing
// the ID/color for rows with a CarID > 5
var cars = from car in data.AsEnumerable()
where
(int)car["CarID"] > 5
select new
{
ID = (int)car["CarID"],
Color = (string)car["Color"]
};
Console.WriteLine("Cars with ID greater than 5:");
foreach (var item in cars)
{
Console.WriteLine("-> CarID = {0} is {1}", item.ID, item.Color);
}
}
{
// Project a new result set containing
// the ID/color for rows with a CarID > 5
var cars = from car in data.AsEnumerable()
where
(int)car["CarID"] > 5
select new
{
ID = (int)car["CarID"],
Color = (string)car["Color"]
};
Console.WriteLine("Cars with ID greater than 5:");
foreach (var item in cars)
{
Console.WriteLine("-> CarID = {0} is {1}", item.ID, item.Color);
}
}
四、DataRowExtensions.Field<T>()
前面的示例都使用了下标和强制类型转换,如果数据类型不一致,可能会导致运行时错误。可以使用 DataRow 的 Field<T>() 扩展方法
var cars = from car in data.AsEnumerable()
where
car.Field<int>("CarID") > 5
select new
{
ID = car.Field<int>("CarID"),
Color = car.Field<string>("Color")
};
where
car.Field<int>("CarID") > 5
select new
{
ID = car.Field<int>("CarID"),
Color = car.Field<string>("Color")
};
这样,就可以在编译时检查数据类型的兼容性了。
五、使用LINQ查询生成新的DataTables - CopyToDataTable<T>()
如果没有使用投影操作,LINQ查询结果集的类型可以用IEnumerable<T>表示,则可以在结果集上使用 CopyToDataTable<T>() 来生成新的 DataTable
static void BuildDataTableFromQuery(DataTable data)
{
var cars = from car in data.AsEnumerable()
where
car.Field<int>("CarID") > 5
select car;
// Use this result set to build a new DataTable.
DataTable newTable = cars.CopyToDataTable();
// Print the DataTable.
for (int curRow = 0; curRow < newTable.Rows.Count; curRow++)
{
for (int curCol = 0; curCol < newTable.Columns.Count; curCol++)
{
Console.Write(newTable.Rows[curRow][curCol].ToString().Trim() + "\t");
}
Console.WriteLine();
}
}
{
var cars = from car in data.AsEnumerable()
where
car.Field<int>("CarID") > 5
select car;
// Use this result set to build a new DataTable.
DataTable newTable = cars.CopyToDataTable();
// Print the DataTable.
for (int curRow = 0; curRow < newTable.Rows.Count; curRow++)
{
for (int curCol = 0; curCol < newTable.Columns.Count; curCol++)
{
Console.Write(newTable.Rows[curRow][curCol].ToString().Trim() + "\t");
}
Console.WriteLine();
}
}
这可以将LINQ查询结果集用在数据绑定中
// Assume myDataGrid is a GUI-based grid object.
myDataGrid.DataSource = (from car in data.AsEnumerable()
where
car.Field<int>("CarID") > 5
select car).CopyToDataTable();
myDataGrid.DataSource = (from car in data.AsEnumerable()
where
car.Field<int>("CarID") > 5
select car).CopyToDataTable();