博客园  :: 首页  :: 联系 :: 管理

C# 2008 学习笔记 - LINQ to ADO.NET(二)- LINQ to DataSet

Posted on 2008-02-22 14:32  sunrack  阅读(2749)  评论(1编辑  收藏  举报
一、获取标准DataSet数据的三种方法
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();
}
}


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();
}


static void AddRowWithTypedDataSet()
{
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;
}

会出现编译错误,提示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"]);
}

由于 EnumerableRowCollection 实现了 IEnumerable<T>,所以,又可以写为:

// Store return value as IEnumerable<T>.
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);
}
}

四、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")
};



这样,就可以在编译时检查数据类型的兼容性了。

 

五、使用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();
}
}

这可以将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();