标签:style blog http io ar color os 使用 sp
Linq是.Net的一個重要的突破,Linq的主要目的是用來作為.Net中的一種通用查詢語言.
Linq設計的目的是針對查詢,不包含新增 修改 刪除等資料異動的功能,因此在EF中Linq當然也只能用於作為查詢,其他部分都與Linq沒有任何關係.
使用Linq的的最大好處是Linq是一種基於物件的強型別的查詢語法,因此可以很容易在編譯時期就能確認語法是否有問題.
對於Linq必須要有個概念,Linq本身設計上是可以跨不同資料來源,譬如XML,DataSet…等等.
所以不同的資料來源會有對應的Linq Library,目前內建於.Net中的Linq Libray.
1.Linq to Object
2.Linq to XML
3.Linq to ADO.Net
而且他的資料來源,Linq提供了擴展方式.譬如網路上可以找到WMI to Linq等相關Library,如果有能力也可以自行設計擴展.
因此相同的對於EF而言,因此EF也擴展了Linq來支持.
Linq在撰寫時有兩種方式
1.Linq語法
List<Customer> customers = ...; var q = from c in customers where c.Id == 1;
2.Lambda表示式
List<Customer> customers = ...; var q = customers.Where(c => c.Id == 1);
這兩種寫法上最後的結果都相同,效能也相同,不過建議使用第2種,對於操作Linq會更有彈性.
EF中對於Linq的擴展比其他資料來源比較複雜些.
底下為EF中的架構圖
由於EF在架構上是沒有綁定資料庫,EF提供了EntityClient Data Provider概念,而Data Provider最終是透過ADO.Net去存取資料庫.
因此當一個非.Net原生支援(目前只有MSSQL)的資料庫要能支援EF必須提供ADO.Net provider外還必須提供EntityClient Data Provider.
EntityClient Data Provider的主要目的是用來轉譯Linq與Entity SQL Query成ADO.Net的Command(SQL).
因此在Linq在EF中並不是所有功能都支持.必須看EntityClient Data Provider有沒有(能不能)將Linq語法轉譯成ADO.Net的Command(SQL).
而對於Linq,EF已經定義了一些標準ANSI通用的查詢對應函數.譬如Contains函數對應LIKE語法.
var q = dbContext.Customers.Where(c => c.Name.Contains("XXX"));
但由於EF設計上並沒有綁定資料庫,因此對於一些特定資料庫的特定功能,EF提供了另外的擴展機制來處理.
譬如在MS-SQL可以透過SqlFunctions這種類別來使用對應到MS-SQL中的特定方法,譬如
var q = dbContext.Customer.Where(c => SqlFunctions.DateDiff("ss", c.CreatedDate, DateTime.Today) > 0);
上面例子透過SqlFunctions中的DateDiff方法去對應SQL語法中的DATEDIFF函數,當然這樣做也代表這個語法綁訂了MS-SQL.
此外對於User Define Function(使用者自訂函數)部分EF也有方式提供擴展,後續章節再針對此部分做說明.
在EF中使用Linq常常會問的問題或是錯誤.
譬如底下的Code
var q = dbContext.Customers.Where(c => c.Name.Contants("XX") && Check(c));
Check函數是另外撰寫用來檢查是否符合的一段C#程式,中間包含了很多複雜邏輯.
由上面的觀念可以知道這個語法執行時一定會出錯,因為EntityClient Data Provider並沒有(也不知道),Check函數應該要怎麼翻譯成ADO.Net的Command(SQL).
所以我們些調整
var q = dbContext.Customers.Where(c => c.Name.Contants("XX")).ToList().Where(c => Check(c));
將語法分為兩段先透過.ToList()方法將資料從資料庫中取回到記憶體中,因為這時候資料已經在記憶體了,因此第二段的Where實際上是透過Linq to Object去操作而非EF.
而要注意一點,在操作EF時必須要了解甚麼時候會把資料從資料庫取回.
否則如果上面的例子寫成如下語法
var q = dbContext.Customers.ToList().Where( c.Name.Contants("XX") && c => Check(c));
雖然結果是相同的,但效能差異相當大
因為.ToList()方法執行時會把所有資料庫中的Customers資料拉回到記憶體中,然後在程式中去執行Where去做塞選.
而前述的方法透過Where(c => c.Name.Contants(“xx”))在查詢時先用SQL語法去塞選結果到記憶體中再做後續檢查.
标签:style blog http io ar color os 使用 sp
原文地址:http://www.cnblogs.com/programlin/p/EF_LINQ.html