Roy's Blog
go on,go on

由 LINQ 存取 ADO.NET 物件(转)

roydux,2010年1月25日


ADO.NET Entity Framework 是一個新的資料存取機制,但因為現存已經大多數使用 ADO.NET 存取資料庫,故與 ADO.NET 之間的連結也是很重要的。

ADO.NET 資料物件
知道 ADO.NET,就應該不會不知道赫赫有名的離線資料庫- DataSet 吧,這個物件與其子物件 DataTable 一起,實作出一個可以儲存資料以及簡單資料搜尋的方式,讓開發人員可以在不連接資料庫的狀況下,存取一個資料庫(或資料表)的複本,而這個複本存在於記憶體中,開發人員可利用 DataTable.Select(),DataTable.Compute() 與 DataView 等物件來存取 DataSet 或 DataTable,無形中可以減少資料庫存取與連線的負擔。因此,在各大以 .NET Framework 為主且以資料庫為核心所開發的應用程式,都可以見到 DataTable 和 DataSet 的身影,而 DataTable 也在某個程度上,扮演了管理資料的角色。

在資料庫和 DataSet/DataTable 間構築資料存取橋樑的工具,就是 DataAdapter,它可以在自動管理連線的情況下,將資料填入 DataSet 或 DataTable 中,在應用 DataSet/DataTable 的程式中也會看到 DataAdapter 的身影,當然不是只有這些物件,也有像 DataReader 與 Command 等物件。

DataSet/DataTable 的基本操作回顧
當資料寫到 DataTable 後,我們可以利用 DataTable.Select() 搜尋資料列;利用 DataTable.Compute() 來計算純量值(Scalar Value);以 DataTable.Rows.Add() 來插入資料列;以 DataTable.Rows.Remove() 來移除資料列。DataSet 則是多個 DataTable 的集合,並且允許在 DataTable 之間有關聯性的存在,關聯性由 DataRelation 來決定。

例如,我們可以利用下列的程式碼來取得一個 Customers 和 Orders 資料表的 DataSet:


SqlConnection conn = new SqlConnection(
    "initial catalog=Northwind; data source=NB\\SQL2008; integrated security=sspi");
SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Customers", conn);
DataSet ds = new DataSet();

adapter.TableMappings.Add("Customers", "Customers");
adapter.TableMappings.Add("Orders", "Orders");

adapter.Fill(ds, "Customers");
adapter.SelectCommand.CommandText = "SELECT * FROM Orders";
adapter.Fill(ds, "Orders");


然後我可以搜尋屬於特定客戶的訂單資料:


DataRow[] results = ds.Tables["Orders"].Select("CustomerID = 'QUICK'");

foreach (DataRow r in results)
   Console.WriteLine("CustomerID ID: {0}, Order ID: {1}", 
r["CustomerID"], r["OrderID"]);


或者計算客戶的訂單數:


Console.WriteLine("Customer: {0}, Orders Count: {1}", 
   "QUICK", ds.Tables["Orders"].Compute("COUNT(OrderID)", "CustomerID = 'QUICK'"));


在資料操作的便利性來看,DataTable 其實是較簡單的,而且簡單的查詢也可以支援,但查詢語法的限制較多。

LINQ to DataSet:更強的資料查詢與檢索
LINQ 除了可以支援一般性 Collection 物件、資料庫與 Entity Framework 之外,也可以應用在 DataSet 與 DataTable 中,稱為 LINQ to DataSet,讓開發人員能夠利用 LINQ 的能力,對 DataSet 做資料檢索與修改,而且語法遵循 LINQ 的標準語法,只有一些小小的不同。

以前面取得 DataSet 的方式為例,我們可以利用 LINQ 來查詢特定客戶的訂單編號:


var query = from o in ds.Tables["Orders"].AsEnumerable()
        where o.Field<string>("CustomerID") == "QUICK"
        select new { 
            OrderID = o.Field<int>("OrderID"), 
            OrderDate = o.Field<DateTime>("OrderDate") };


也可以查詢特定客戶的訂單數:


var query = from o in ds.Tables["Orders"].AsEnumerable()
            where o.Field<string>("CustomerID") == "QUICK"
            group o by o.Field<string>("CustomerID");

Console.WriteLine(query.First().Count().ToString());


修改資料
LINQ to DataSet 除了可以檢索資料外,也可以修改指定的資料,例如下列這一支程式碼:


DataTable table = new DataTable();
table.Columns.Add("CustomerID", typeof(System.Guid));
table.Columns.Add("CustomerName", typeof(string));

table.Rows.Add(new object[] { Guid.NewGuid(), "AAA" });
table.Rows.Add(new object[] { Guid.NewGuid(), "BBB" });
table.Rows.Add(new object[] { Guid.NewGuid(), "CCC" });
table.Rows.Add(new object[] { Guid.NewGuid(), "DDD" });

var query = from t in table.AsEnumerable()
              select t;

foreach (var r in query)
    Console.WriteLine("ID: {0}, NAME: {1}",
        r.Field<System.Guid>("CustomerID"), r.Field<string>("CustomerName"));


若想要修改最後一列的資料為EEE的話,可以下這樣的語法:


query.Last().SetField("CustomerName", "EEE");


你也可以利用迴圈來處理值的問題,例如:


DataTable table = new DataTable();
table.Columns.Add("CustomerID", typeof(System.Guid));
table.Columns.Add("CustomerName", typeof(string));
table.Columns.Add("Qty", typeof(int));
table.Columns.Add("Price", typeof(int));
table.Columns.Add("Amount", typeof(int));

table.Rows.Add(new object[] { Guid.NewGuid(), "AAA", 5, 200, 0 });
table.Rows.Add(new object[] { Guid.NewGuid(), "BBB", 8, 540, 0 });
table.Rows.Add(new object[] { Guid.NewGuid(), "CCC", 6, 320, 0 });
table.Rows.Add(new object[] { Guid.NewGuid(), "DDD", 3, 290, 0 });

var query = from t in table.AsEnumerable()
              select t;

foreach (var r in query)
{
    r.SetField<int>("Amount", r.Field<int>("Qty") * r.Field<int>("Price"));
    Console.WriteLine("ID: {0}, NAME: {1}, AMOUNT: {2}",
        r.Field<System.Guid>("CustomerID"), r.Field<string>("CustomerName"), 
r.Field("Amount"));



不過目前的 LINQ 規格,無法插入與刪除 DataRow,開發人員仍然要以原本的方法來設計。

關聯性查詢
DataSet 可以包含許多的 DataTable,在 DataTable 間也可以設定 DataRelation 來做關聯設定,LINQ 可以針對這個關聯設定來查詢資料,例如用關聯性的方式查詢顧客的訂單列表:


var query = from c in ds.Tables["Customers"].AsEnumerable()
            join o in ds.Tables["Orders"].AsEnumerable()
            on c.Field<string>("CustomerID") equals o.Field<string>("CustomerID")
            select new  {
                CustomerID = c.Field<string>("CustomerID"),
                OrderID = o.Field<int>("OrderID")
            };


下一步
由於 LINQ to DataSet 較為簡單,故用少量的篇幅來介紹,接下來我們會進入應用程式中,來說明如何在應用程式中整合 ADO.NET Entity Framework 與 LINQ 功能。



原文地址:http://www.microsoft.com/taiwan/msdn/columns/jhu_ming_jhong/ADO.NET_Entity_Framework_Interaction_to_ADO.NET_data_objects.htm

Tags: ADO.NET Entity Framework  

分类: .NET | 评论:0 | 浏览:

相关文章:

发表评论