在LINQ2SQL中,所有的數據操作的入口都是DataContext對象,如下面的代碼示例了訪問Northwnd數據庫的Customer數據:
01 class Program
02 {
03 static void Main(string[] args)
04 {
05 using(var context = CreateContext())
06 {
07 context.Log = Console.Out;
08 var customers = context.GetTable<Customer>().Take(10);
09
10 foreach (var item in customers)
11 {
12 Console.WriteLine(item.CompanyName);
13 }
14 }
15 }
16
17 static DataContext CreateContext()
18 {
19 var path = System.IO.Path.Combine(
20 AppDomain.CurrentDomain.BaseDirectory, "northwnd.xml");
21 var connectionString = System.IO.Path.Combine(
22 AppDomain.CurrentDomain.BaseDirectory, "northwnd.mdf");
23 var mapping = XmlMappingSource.FromXml(System.IO.File.ReadAllText(path));
24 var context = new DataContext(connectionString, mapping);
25
26 return context;
27 }
28 }
更完整的通過DataContext實現SqlServer數據庫的CRUD操作的方法,請參考LINQ那些事兒(2)- 簡單對象的CRUD操作和Association的級聯操作。 CreateContext()函數通過傳遞數據庫mdf文件的路徑和映射信息,構造了一個DataContext對象,通過DataContext對象,我們可以對該數據庫進行任何的操作,包括CRUD,甚至是刪除或創建一個新的數據庫文件。為了便於示例,本文用了Sqlexpress的本地數據庫文件,你可以修改connectionString指向正式SqlSever上的數據庫。
關於DataContext的詳細說明,請參考MSDN:http://msdn.microsoft.com/zh-cn/library/system.data.linq.datacontext.aspx
我們來關注傳遞給DataContext構造函數的第二個參數——mapping,mapping對象中包含了Northwnd數據庫和實體類之間的映射關系。LINQ2SQL通過System.Data.Linq.Mapping.MappingSource來作為映射關系的基類,並且在.Net Framework 3.5中提供了AttributeMappingSource和XmlMappingSource,分別表示了兩種定義映射關系的方法——通過在實體類上用Attribute標簽來定義,以及通過外部Xml文件來定義映射關系。
當使用一些開源的ORM框架時,你可能不得不手寫定義這些映射信息,或者通過第三方的工具來實現映射信息的生成。對於LINQ2SQL,同樣可以用手寫定義,但是微軟已經為我們提供了足夠好的生成工具——O/R Designer和SqlMetal。
參考資料:
基於屬性的映射http://msdn.microsoft.com/zh-cn/library/bb386971.aspx
使用O/R Designer生成對象模型 http://msdn.microsoft.com/zh-cn/library/bb384429.aspx
使用SqlMetal.exe生成對象模型http://msdn.microsoft.com/zh-cn/library/bb386987.aspx
通過O/R Desginer或SqlMetal,你不但可以生成實體類的定義,而且還生成了一個DataContext的派生類,名稱為 xxxDataContext(xxx為默認數據庫的名稱,也可以自行定義)。在文章開始的代碼中,我們通過 DataContext.GetTable<Customer>()來獲取操作Customer表的表對象,但在 xxxDataContext類中提供了更方便的方法,通過訪問xxxDataContext類中包含的Customers屬性即可。
需要注意的是,在SqlServer中你允許設計一張沒有主鍵標識(Primary key)的數據表,但是在定義entity class的屬性時,必須至少包含一個的主鍵屬性(IsPrimaryKey=true)。這不單是數據庫設計標准的要求,DataContext對象會使用PrimaryKey屬性值作為實體對象的唯一標識,用來進行實體對象的生命周期管理,詳見LINQ那些事(6)。
我不建議你使用手寫的方法來定義entity class,甚至是必須用O/R Designer或Sqlmetal來生成entity class,因為對於包含關聯關系(Association)的entity class,自動生成的代碼中還包含了維護Association的代碼,這對LINQ2SQL實現級聯操作是非常關鍵的(你可以看看生成的 Customer類的代碼,它如何維護Orders屬性)。
還有一個問題是通過Attribute標簽和Xml映射文件來定義映射關系,孰優孰劣的問題,這已經是一個老問題了。聽到最多的是,有人說大項目用 XML方式,小項目用Attribute方式,我覺得那純粹是瞎扯淡,但XML方式的確有一個好處就是有時當數據庫發生更改時,我們直接修改XML就可以了,而無需重新編譯代碼,其他的更多就是習慣問題了。在這一系列的文章中,我都采用了XML的方式來定義,文章開始的代碼示例了如何由XML來創建 DataContext對象,你只需把DataContext改成xxxDataContext即可。
順便提供幾個非常常用的sqlmetal參數組合:(拷貝時注意去掉northwnd.和cs之間的斷行)
* 1、生成本地數據庫文件的映射:sqlmetal "northwnd.mdf" /code:northwnd.
cs /map:northwnd.xml /namespace:LinqAttach /context:Northwnd /pluralize
* 2、通過鏈接字符串:sqlmetal /conn:”server=myserver; database=northwind” /code:northwnd.
cs /map:northwnd.xml /namespace:LinqAttach /context:Northwnd /pluralize
* 3、通過指定數據源:sqlmetal /server:myserver /database:northwnd /password:pwd /code:northwnd.
cs /map:northwnd.xml /namespace:LinqAttach /context:Northwnd /pluralize
說明:
/code:指定包含生成實體類和派生DataContext類的cs代碼的文件路徑
/map:指定生成xml映射文件路徑
/namespace:指定生成的cs代碼所在的命名空間
/context:指定生成的派生DataContext類的類名
/pluralize:指定sqlmetal根據英文單/復數規則來生成實體類和屬性的名稱,非常靠譜。