十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
來自森大科技官方博客
http://www.cnsendblog.com/index.php/?p=175
GPS平臺、網(wǎng)站建設(shè)、軟件開發(fā)、系統(tǒng)運維,找森大網(wǎng)絡(luò)科技!
http://cnsendnet.taobao.com
網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)公司!專注于網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、小程序定制開發(fā)、集團企業(yè)網(wǎng)站建設(shè)等服務(wù)項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了貢覺免費建站歡迎大家使用!
到現(xiàn)在為止你還未觸碰LINQ,那進來吧 —— LINQ入門(完結(jié)篇)
前 言
各種懶惰,各種拖沓,終究是要動筆寫終結(jié)篇了,在這個系列的前幾篇文章里我們主要學(xué)習(xí)linq的基礎(chǔ)語法以及他對內(nèi)存數(shù)據(jù)的操作等,那么本篇文章我們將討論學(xué)習(xí)最為大家所熟悉的,也是最受爭議的 Linq To SQL,再次強調(diào),如果你到目前為止認為LinqToSql就是linq的話,有以下幾種方式可共君選擇:1.把這個系列的前面幾篇文章給讀了。2.到菜市場賣塊豆腐給撞了。3.(MM可以忽略跳過哈)把屁股洗干凈,讓大家把你菊花給爆了。
用 意
Linq To Sql 相對現(xiàn)在來說,不可否認它已經(jīng)過時了,伴隨著vs2010和Entity Fromwork 4的出現(xiàn),linq to sql 退出歷史舞臺是必然的,因為EF4比之更強大更完善。但是linq to sql 并不是一無是處,有很多東西它與EF4是相通的,簡單的了解linq to sql并無害處,并且還可以對EF4有一定的過渡幫助。
由于這個主題能講的內(nèi)容非常多,篇幅關(guān)系不能全部說完,在這里只能簡單地向大家分享個大概,敬請諒解。
目 錄
什么是Linq To Sql
生成實體
增刪改查
普通查詢
關(guān)聯(lián)查詢
數(shù)據(jù)新增
數(shù)據(jù)刪除
數(shù)據(jù)更新
拓展
優(yōu)缺雜談
總結(jié)
索引
什么是Linq To Sql
摘自MSDN:LINQ to SQL 是 .NET Framework 3.5 版的一個組件,提供了用于將關(guān)系數(shù)據(jù)作為對象管理的運行時基礎(chǔ)結(jié)構(gòu)。 在 LINQ to SQL 中,關(guān)系數(shù)據(jù)庫的數(shù)據(jù)模型映射到用開發(fā)人員所用的編程語言表示的對象模型。 當應(yīng)用程序運行時,LINQ to SQL 會將對象模型中的語言集成查詢轉(zhuǎn)換為 SQL,然后將它們發(fā)送到數(shù)據(jù)庫進行執(zhí)行。當數(shù)據(jù)庫返回結(jié)果時,LINQ to SQL 會將它們轉(zhuǎn)換回您可以用您自己的編程語言處理的對象。簡單的理解就是我們對數(shù)據(jù)進行實體化操作,例如我們可以吧每章表作為一個數(shù)據(jù)實體封裝操作。
生成實體
在linq to sql中,實體對象時一個非常重要的環(huán)節(jié),他是對數(shù)據(jù)表,視圖等對象的映射,沒有實體就談不上linq to sql了。也許有些老手會反對為什么是生成實體而不是手寫實體,生成實體會產(chǎn)生冗余代碼。個人認為對于初學(xué)者來說,我們很多手頭上的項目通??偸窍扔袔毂砗笥写a,那么我們會針對庫表進行編寫實體,這真的是個體力活沒有任何捷徑可言,一張一張表的寫實體非常痛苦。所以干脆讓大家直接生成,即省事又方便,而且也可以學(xué)到怎樣編寫比較專業(yè)的實體。
既然是生成實體,那么這肯定需要一些而外的工具了,在這里MS自VS2008起就給我們提供了這么一個工具SqlMetal.exe命令工具,可為 LINQ to SQL 組件生成代碼和映射。那么接下來我們演示如何生成實體
1.假設(shè)我們有一張用戶表,如圖:
2.打開VS2008命令行工具,如圖:
3.輸入命令,生成數(shù)據(jù)實體。注意:生成實體文件分別有2種,一種是.cs文件和.xml映射文件的組合方式,另一種則是.dbml文件,只能二選一,切記??!
首先我們先生成第一種:.cs和*.xml組合方式,如圖:
4.根據(jù)命令指定的位置,我們可以看到對應(yīng)的生成文件,如圖:
5.將生成的文件放入我們的項目中,如圖:
注意,在這里我們要選中“l(fā)inqToSqlMap.xml”,在屬性對話框里設(shè)置始終復(fù)制到輸出目錄里,如圖:
6.接下來,我們看看類文件,生成了那些實體代碼,如圖:
xml 映射配置文件
從上圖看,生成的代碼貌似有點多,但是這要比我們自己手寫代碼更專業(yè)。實體文件主要分為兩部分,一是數(shù)據(jù)庫上下文關(guān)聯(lián)類 LinqToSqlDemo,二是對應(yīng)表的實體類 Users 。到這里我們對第一種組合方式的實體生成就已完成。
接下來我們看看要是我們使用的是生成*.dbml文件又會什么樣的場景呢。
1.同上,輸入命令生成文件,如圖:
2.查看生成文件,如圖:
3.將生成的DBML文件放入項目里,我們可以看到,生成的只有一個文件,但是當添加到項目里時,項目會自動生成layout和designer兩個文件,如圖:
4.有意思東西來了,右鍵點擊dbml文件,選擇視圖設(shè)計器,我們可以在編輯框中得到實體映射編輯視圖
5.我們看一下這個時候在.designer.cs文件里生成了哪些內(nèi)容
可以看到,生成的實體文件和上一種方式生成的實體文件區(qū)別不大,由于沒有了XML映射配置,所以這里采用的是特性映射配置,在Users實體類中我們可以看到附加了一些如Table,Column的特性標記。
到此我們對實體生成的做法有了一個基本的認識,接下來我們看看linq 是怎么通過實體進行增刪改查的
LinqToSql 增刪改查
1.DataContext 實例
既然要對數(shù)據(jù)進行CURD,那么我們就需通過對數(shù)據(jù)庫上下文關(guān)聯(lián)類的實例進行操作之,即DataContext派生類,如上面生成的LinqToSqlDemo派生類。
由于DataContext 具有多個重載構(gòu)造函數(shù),在這里針對先前的2種實體生成方式對具體的2個構(gòu)造函數(shù)進行描述,其他的就不逐個介紹少了。詳情可以查閱MSDN
如果使用的是.cs 與 .xml組合方式的實體映射,那么在構(gòu)造實例應(yīng)該如下
如果使用的是.dbml文件的實體映射,那么就簡單了,直接提供數(shù)據(jù)庫連接字符串就可以,因為在派生類的內(nèi)部已經(jīng)指定使用特性映射配置。見下圖
2.查詢數(shù)據(jù)
// 假設(shè)我們已構(gòu)造了DataContext對象實例dataContext
// 屬性log是實例內(nèi)部的操作日志輸出,它屬于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();
輸出結(jié)果:
如果我們帶上where 條件,查詢的操作又是如何的呢
// 假設(shè)我們已構(gòu)造了DataContext對象實例dataContext
// 屬性log是實例內(nèi)部的操作日志輸出,它屬于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();
輸出結(jié)果:(這里我們可以看到sql使用了參數(shù)化查詢)
3.關(guān)聯(lián)查詢
往往在實際項目中我們會涉及到幾個表的關(guān)聯(lián)查詢,那么LinqToSql有時怎樣支持的呢。
假設(shè)多了一張用戶詳細表,他與用戶表的關(guān)系如下:
生成實體(.dbml):
在生成的實體代碼.designer.cs文件中我們會看到,Users 實體類多了一個EntityRef
查詢:
// 假設(shè)我們已構(gòu)造了DataContext對象實例dataContext
// 屬性log是實例內(nèi)部的操作日志輸出,它屬于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();
輸出結(jié)果:
從結(jié)果我們可以看到,首先是把用戶表給查了,然后根據(jù)linq延遲加載的特性,只有真正使用時才執(zhí)行,因此當需要查看用戶詳細信息時才會去執(zhí)行用戶詳細查詢,這樣就帶來了很大弊端,如果數(shù)據(jù)量大時那么這樣的查詢開銷就大了,大大降低了程序的效率。那么這個問題是否可以解決呢?答案是肯定的,請看下面代碼:
// DataLoadOption數(shù)據(jù)導(dǎo)入操作對象,它可以告訴linq在執(zhí)行查詢是否延遲
// 查詢對象的子對象
var loadOption = new DataLoadOptions();
// 設(shè)置數(shù)據(jù)導(dǎo)入對象關(guān)聯(lián)關(guān)系
loadOption.LoadWith
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();
輸出結(jié)果:
從log我們可以看到這樣就是一條語句查出來數(shù)據(jù)結(jié)果集。注意,這里演示的是2表關(guān)系的查詢,如果當我們再多出一個表,而這表是與用戶詳細表形成關(guān)聯(lián)關(guān)系的時候那么,DataLoadoption 就沒法解決了一次性查出,而又回到類似上一個樣例分次查出來。例如:
假設(shè)新增一張表(UserDetails2):
關(guān)系如下:
生成*.dbml:
查詢:
// 假設(shè)我們已構(gòu)造了DataContext對象實例dataContext
// 屬性log是實例內(nèi)部的操作日志輸出,它屬于Stream類型
dataContext.Log = Console.Out;
// DataLoadOption數(shù)據(jù)導(dǎo)入操作對象,它可以告訴linq在執(zhí)行查詢是否延遲
// 查詢對象的子對象
var loadOption = new DataLoadOptions();
// 設(shè)置數(shù)據(jù)導(dǎo)入對象關(guān)聯(lián)關(guān)系
loadOption.LoadWith
// 加入對表UserDetails2的關(guān)聯(lián)
loadOption.LoadWith
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();
查詢結(jié)果:
來自森大科技官方博客
http://www.cnsendblog.com/index.php/?p=175
GPS平臺、網(wǎng)站建設(shè)、軟件開發(fā)、系統(tǒng)運維,找森大網(wǎng)絡(luò)科技!
http://cnsendnet.taobao.com