您好,登錄后才能下訂單哦!
來自森大科技官方博客
http://www.cnsendblog.com/index.php/?p=175
GPS平臺、網站建設、軟件開發(fā)、系統(tǒng)運維,找森大網絡科技!
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
生成實體
增刪改查
普通查詢
關聯查詢
數據新增
數據刪除
數據更新
拓展
優(yōu)缺雜談
總結
索引
什么是Linq To Sql
摘自MSDN:LINQ to SQL 是 .NET Framework 3.5 版的一個組件,提供了用于將關系數據作為對象管理的運行時基礎結構。 在 LINQ to SQL 中,關系數據庫的數據模型映射到用開發(fā)人員所用的編程語言表示的對象模型。 當應用程序運行時,LINQ to SQL 會將對象模型中的語言集成查詢轉換為 SQL,然后將它們發(fā)送到數據庫進行執(zhí)行。當數據庫返回結果時,LINQ to SQL 會將它們轉換回您可以用您自己的編程語言處理的對象。簡單的理解就是我們對數據進行實體化操作,例如我們可以吧每章表作為一個數據實體封裝操作。
生成實體
在linq to sql中,實體對象時一個非常重要的環(huán)節(jié),他是對數據表,視圖等對象的映射,沒有實體就談不上linq to sql了。也許有些老手會反對為什么是生成實體而不是手寫實體,生成實體會產生冗余代碼。個人認為對于初學者來說,我們很多手頭上的項目通常總是先有庫表后有代碼,那么我們會針對庫表進行編寫實體,這真的是個體力活沒有任何捷徑可言,一張一張表的寫實體非常痛苦。所以干脆讓大家直接生成,即省事又方便,而且也可以學到怎樣編寫比較專業(yè)的實體。
既然是生成實體,那么這肯定需要一些而外的工具了,在這里MS自VS2008起就給我們提供了這么一個工具SqlMetal.exe命令工具,可為 LINQ to SQL 組件生成代碼和映射。那么接下來我們演示如何生成實體
1.假設我們有一張用戶表,如圖:
2.打開VS2008命令行工具,如圖:
3.輸入命令,生成數據實體。注意:生成實體文件分別有2種,一種是.cs文件和.xml映射文件的組合方式,另一種則是.dbml文件,只能二選一,切記??!
首先我們先生成第一種:.cs和*.xml組合方式,如圖:
4.根據命令指定的位置,我們可以看到對應的生成文件,如圖:
5.將生成的文件放入我們的項目中,如圖:
注意,在這里我們要選中“l(fā)inqToSqlMap.xml”,在屬性對話框里設置始終復制到輸出目錄里,如圖:
6.接下來,我們看看類文件,生成了那些實體代碼,如圖:
xml 映射配置文件
從上圖看,生成的代碼貌似有點多,但是這要比我們自己手寫代碼更專業(yè)。實體文件主要分為兩部分,一是數據庫上下文關聯類 LinqToSqlDemo,二是對應表的實體類 Users 。到這里我們對第一種組合方式的實體生成就已完成。
接下來我們看看要是我們使用的是生成*.dbml文件又會什么樣的場景呢。
1.同上,輸入命令生成文件,如圖:
2.查看生成文件,如圖:
3.將生成的DBML文件放入項目里,我們可以看到,生成的只有一個文件,但是當添加到項目里時,項目會自動生成layout和designer兩個文件,如圖:
4.有意思東西來了,右鍵點擊dbml文件,選擇視圖設計器,我們可以在編輯框中得到實體映射編輯視圖
5.我們看一下這個時候在.designer.cs文件里生成了哪些內容
可以看到,生成的實體文件和上一種方式生成的實體文件區(qū)別不大,由于沒有了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延遲加載的特性,只有真正使用時才執(zhí)行,因此當需要查看用戶詳細信息時才會去執(zhí)行用戶詳細查詢,這樣就帶來了很大弊端,如果數據量大時那么這樣的查詢開銷就大了,大大降低了程序的效率。那么這個問題是否可以解決呢?答案是肯定的,請看下面代碼:
// DataLoadOption數據導入操作對象,它可以告訴linq在執(zhí)行查詢是否延遲
// 查詢對象的子對象
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在執(zhí)行查詢是否延遲
// 查詢對象的子對象
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平臺、網站建設、軟件開發(fā)、系統(tǒng)運維,找森大網絡科技!
http://cnsendnet.taobao.com
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。