您好,登錄后才能下訂單哦!
來自森大科技官方博客
http://www.cnsendblog.com/index.php/?p=175
GPS平臺、網站建設、軟件開發、系統運維,找森大網絡科技!
http://cnsendnet.taobao.com
到現在為止你還未觸碰LINQ,那進來吧 —— LINQ入門(完結篇)
前 言
各種懶惰,各種拖沓,終究是要動筆寫終結篇了,在這個系列的前幾篇文章里我們主要學習linq的基礎語法以及他對內存數據的操作等,那么本篇文章我們將討論學習最為大家所熟悉的,也是最受爭議的 Linq To SQL,再次強調,如果你到目前為止認為LinqToSql就是linq的話,有以下幾種方式可共君選擇:1.把這個系列的前面幾篇文章給讀了。2.到菜市場賣塊豆腐給撞了。3.(MM可以忽略跳過哈)把屁股洗干凈,讓大家把你菊花給爆了。
用 意
Linq To Sql 相對現在來說,不可否認它已經過時了,伴隨著vs2010和Entity Fromwork 4的出現,linq to sql 退出歷史舞臺是必然的,因為EF4比之更強大更完善。但是linq to sql 并不是一無是處,有很多東西它與EF4是相通的,簡單的了解linq to sql并無害處,并且還可以對EF4有一定的過渡幫助。
由于這個主題能講的內容非常多,篇幅關系不能全部說完,在這里只能簡單地向大家分享個大概,敬請諒解。
目 錄
什么是Linq To Sql
生成實體
增刪改查
普通查詢
關聯查詢
數據新增
數據刪除
數據更新
拓展
優缺雜談
總結
索引
什么是Linq To Sql
摘自MSDN:LINQ to SQL 是 .NET Framework 3.5 版的一個組件,提供了用于將關系數據作為對象管理的運行時基礎結構。 在 LINQ to SQL 中,關系數據庫的數據模型映射到用開發人員所用的編程語言表示的對象模型。 當應用程序運行時,LINQ to SQL 會將對象模型中的語言集成查詢轉換為 SQL,然后將它們發送到數據庫進行執行。當數據庫返回結果時,LINQ to SQL 會將它們轉換回您可以用您自己的編程語言處理的對象。簡單的理解就是我們對數據進行實體化操作,例如我們可以吧每章表作為一個數據實體封裝操作。
生成實體
在linq to sql中,實體對象時一個非常重要的環節,他是對數據表,視圖等對象的映射,沒有實體就談不上linq to sql了。也許有些老手會反對為什么是生成實體而不是手寫實體,生成實體會產生冗余代碼。個人認為對于初學者來說,我們很多手頭上的項目通常總是先有庫表后有代碼,那么我們會針對庫表進行編寫實體,這真的是個體力活沒有任何捷徑可言,一張一張表的寫實體非常痛苦。所以干脆讓大家直接生成,即省事又方便,而且也可以學到怎樣編寫比較專業的實體。
既然是生成實體,那么這肯定需要一些而外的工具了,在這里MS自VS2008起就給我們提供了這么一個工具SqlMetal.exe命令工具,可為 LINQ to SQL 組件生成代碼和映射。那么接下來我們演示如何生成實體
1.假設我們有一張用戶表,如圖:
2.打開VS2008命令行工具,如圖:
3.輸入命令,生成數據實體。注意:生成實體文件分別有2種,一種是.cs文件和.xml映射文件的組合方式,另一種則是.dbml文件,只能二選一,切記!!
首先我們先生成第一種:.cs和*.xml組合方式,如圖:
4.根據命令指定的位置,我們可以看到對應的生成文件,如圖:
5.將生成的文件放入我們的項目中,如圖:
注意,在這里我們要選中“linqToSqlMap.xml”,在屬性對話框里設置始終復制到輸出目錄里,如圖:
6.接下來,我們看看類文件,生成了那些實體代碼,如圖:
xml 映射配置文件
從上圖看,生成的代碼貌似有點多,但是這要比我們自己手寫代碼更專業。實體文件主要分為兩部分,一是數據庫上下文關聯類 LinqToSqlDemo,二是對應表的實體類 Users 。到這里我們對第一種組合方式的實體生成就已完成。
接下來我們看看要是我們使用的是生成*.dbml文件又會什么樣的場景呢。
1.同上,輸入命令生成文件,如圖:
2.查看生成文件,如圖:
3.將生成的DBML文件放入項目里,我們可以看到,生成的只有一個文件,但是當添加到項目里時,項目會自動生成layout和designer兩個文件,如圖:
4.有意思東西來了,右鍵點擊dbml文件,選擇視圖設計器,我們可以在編輯框中得到實體映射編輯視圖
5.我們看一下這個時候在.designer.cs文件里生成了哪些內容
可以看到,生成的實體文件和上一種方式生成的實體文件區別不大,由于沒有了XML映射配置,所以這里采用的是特性映射配置,在Users實體類中我們可以看到附加了一些如Table,Column的特性標記。
到此我們對實體生成的做法有了一個基本的認識,接下來我們看看linq 是怎么通過實體進行增刪改查的
LinqToSql 增刪改查
1.DataContext 實例
既然要對數據進行CURD,那么我們就需通過對數據庫上下文關聯類的實例進行操作之,即DataContext派生類,如上面生成的LinqToSqlDemo派生類。
由于DataContext 具有多個重載構造函數,在這里針對先前的2種實體生成方式對具體的2個構造函數進行描述,其他的就不逐個介紹少了。詳情可以查閱MSDN
如果使用的是.cs 與 .xml組合方式的實體映射,那么在構造實例應該如下
如果使用的是.dbml文件的實體映射,那么就簡單了,直接提供數據庫連接字符串就可以,因為在派生類的內部已經指定使用特性映射配置。見下圖
2.查詢數據
// 假設我們已構造了DataContext對象實例dataContext
// 屬性log是實例內部的操作日志輸出,它屬于Stream類型
dataContext.Log = Console.Out;
var users = from usr in dataContext.Users
select usr;
foreach (var usr in users)
{
Console.WriteLine("用戶名:{0},Email:{1}", usr.UserName, usr.Email);
}
Console.Read();
輸出結果:
如果我們帶上where 條件,查詢的操作又是如何的呢
// 假設我們已構造了DataContext對象實例dataContext
// 屬性log是實例內部的操作日志輸出,它屬于Stream類型
dataContext.Log = Console.Out;
var users = from usr in dataContext.Users
where usr.UserName == "張三"
select usr;
foreach (var usr in users)
{
Console.WriteLine("用戶名:{0},Email:{1}", usr.UserName, usr.Email);
}
Console.Read();
輸出結果:(這里我們可以看到sql使用了參數化查詢)
3.關聯查詢
往往在實際項目中我們會涉及到幾個表的關聯查詢,那么LinqToSql有時怎樣支持的呢。
假設多了一張用戶詳細表,他與用戶表的關系如下:
生成實體(.dbml):
在生成的實體代碼.designer.cs文件中我們會看到,Users 實體類多了一個EntityRef<UserDetails> _UserDetails私有字段,而在UserDetails實體類中對了一個EntityRef<Users> _Users私有字段,泛型類EntityRef<T>是關鍵,他是實體之間關聯關系處理主要對象。篇幅關系詳情請查閱MSDN點擊這里
查詢:
// 假設我們已構造了DataContext對象實例dataContext
// 屬性log是實例內部的操作日志輸出,它屬于Stream類型
dataContext.Log = Console.Out;
var users = from usr in dataContext.Users
select usr;
foreach (var usr in users)
{
Console.WriteLine("用戶名:{0},Email:{1},年齡{2},住址:{3}",
usr.UserName, usr.Email, usr.UserDetails.Age, usr.UserDetails.Address);
}
Console.Read();
輸出結果:
從結果我們可以看到,首先是把用戶表給查了,然后根據linq延遲加載的特性,只有真正使用時才執行,因此當需要查看用戶詳細信息時才會去執行用戶詳細查詢,這樣就帶來了很大弊端,如果數據量大時那么這樣的查詢開銷就大了,大大降低了程序的效率。那么這個問題是否可以解決呢?答案是肯定的,請看下面代碼:
// DataLoadOption數據導入操作對象,它可以告訴linq在執行查詢是否延遲
// 查詢對象的子對象
var loadOption = new DataLoadOptions();
// 設置數據導入對象關聯關系
loadOption.LoadWith<Users>(usr => usr.UserDetails);
dataContext.LoadOptions = loadOption;
var users = from usr in dataContext.Usersselect usr;
foreach (var usr in users)
{
Console.WriteLine("用戶名:{0},Email:{1},年齡:{2},住址:{3}",
usr.UserName, usr.Email, usr.UserDetails.Age, usr.UserDetails.Address);
}
Console.Read();
輸出結果:
從log我們可以看到這樣就是一條語句查出來數據結果集。注意,這里演示的是2表關系的查詢,如果當我們再多出一個表,而這表是與用戶詳細表形成關聯關系的時候那么,DataLoadoption 就沒法解決了一次性查出,而又回到類似上一個樣例分次查出來。例如:
假設新增一張表(UserDetails2):
關系如下:
生成*.dbml:
查詢:
// 假設我們已構造了DataContext對象實例dataContext
// 屬性log是實例內部的操作日志輸出,它屬于Stream類型
dataContext.Log = Console.Out;
// DataLoadOption數據導入操作對象,它可以告訴linq在執行查詢是否延遲
// 查詢對象的子對象
var loadOption = new DataLoadOptions();
// 設置數據導入對象關聯關系
loadOption.LoadWith<Users>(usr => usr.UserDetails);
// 加入對表UserDetails2的關聯
loadOption.LoadWith<UserDetails>(dtl => dtl.UserDetails2);
dataContext.LoadOptions = loadOption;
var users = from usr in dataContext.Users
select usr;
foreach (var usr in users)
{
Console.Write("用戶名:{0},Email:{1},年齡:{2},住址:{3}",
usr.UserName, usr.Email, usr.UserDetails.Age, usr.UserDetails.Address);
foreach (var dtl in usr.UserDetails.UserDetails2)
{
Console.Write(",性別:{0}", dtl.Sex);
}
Console.Write("\r\n");
}
Console.Read();
查詢結果:
來自森大科技官方博客
http://www.cnsendblog.com/index.php/?p=175
GPS平臺、網站建設、軟件開發、系統運維,找森大網絡科技!
http://cnsendnet.taobao.com
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。