LINQ入門(完結篇)

來自森大科技官方博客
http://www.cnsendblog.com/index.php/?p=175
GPS平臺、網站建設、軟件開發、系統運維,找森大網絡科技!
http://cnsendnet.taobao.comphp

到如今爲止你還未觸碰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.假設咱們有一張用戶表,如圖:
LINQ入門(完結篇)
  2.打開VS2008命令行工具,如圖:
LINQ入門(完結篇)
3.輸入命令,生成數據實體。注意:生成實體文件分別有2種,一種是.cs文件和.xml映射文件的組合方式,另外一種則是.dbml文件,只能二選一,切記!!
  首先咱們先生成第一種:
.cs和*.xml組合方式,如圖:
LINQ入門(完結篇)
  4.根據命令指定的位置,咱們能夠看到對應的生成文件,如圖:
LINQ入門(完結篇)
 5.將生成的文件放入咱們的項目中,如圖:
LINQ入門(完結篇)
注意,在這裏咱們要選中「linqToSqlMap.xml」,在屬性對話框裏設置始終複製到輸出目錄裏,如圖:
LINQ入門(完結篇)sql

 6.接下來,咱們看看類文件,生成了那些實體代碼,如圖:
LINQ入門(完結篇)
 xml 映射配置文件
LINQ入門(完結篇)
從上圖看,生成的代碼貌似有點多,可是這要比咱們本身手寫代碼更專業。實體文件主要分爲兩部分,一是數據庫上下文關聯類 LinqToSqlDemo,二是對應表的實體類 Users 。到這裏咱們對第一種組合方式的實體生成就已完成。
  接下來咱們看看要是咱們使用的是生成*.dbml文件又會什麼樣的場景呢。
  1.同上,輸入命令生成文件,如圖:
LINQ入門(完結篇)數據庫

 2.查看生成文件,如圖:
LINQ入門(完結篇)
3.將生成的DBML文件放入項目裏,咱們能夠看到,生成的只有一個文件,可是當添加到項目裏時,項目會自動生成layout和designer兩個文件,如圖:
LINQ入門(完結篇)
 4.有意思東西來了,右鍵點擊dbml文件,選擇視圖設計器,咱們能夠在編輯框中獲得實體映射編輯視圖
LINQ入門(完結篇)
LINQ入門(完結篇)
5.咱們看一下這個時候在.designer.cs文件裏生成了哪些內容
LINQ入門(完結篇)
能夠看到,生成的實體文件和上一種方式生成的實體文件區別不大,因爲沒有了XML映射配置,因此這裏採用的是特性映射配置,在Users實體類中咱們能夠看到附加了一些如Table,Column的特性標記。
  到此咱們對實體生成的作法有了一個基本的認識,接下來咱們看看linq 是怎麼經過實體進行增刪改查的
LinqToSql 增刪改查
  1.DataContext 實例
  既然要對數據進行CURD,那麼咱們就需經過對數據庫上下文關聯類的實例進行操做之,即DataContext派生類,如上面生成的LinqToSqlDemo派生類。
  因爲DataContext 具備多個重載構造函數,在這裏針對先前的2種實體生成方式對具體的2個構造函數進行描述,其餘的就不逐個介紹少了。詳情能夠查閱MSDN
  若是使用的是
.cs 與 .xml組合方式的實體映射,那麼在構造實例應該以下
LINQ入門(完結篇)
若是使用的是
.dbml文件的實體映射,那麼就簡單了,直接提供數據庫鏈接字符串就能夠,由於在派生類的內部已經指定使用特性映射配置。見下圖
LINQ入門(完結篇)
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();ide

  輸出結果:
LINQ入門(完結篇)
若是咱們帶上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使用了參數化查詢)
LINQ入門(完結篇)
3.關聯查詢
  每每在實際項目中咱們會涉及到幾個表的關聯查詢,那麼LinqToSql有時怎樣支持的呢。
  假設多了一張用戶詳細表,他與用戶表的關係以下:
LINQ入門(完結篇)

生成實體(.dbml):
LINQ入門(完結篇)
在生成的實體代碼
.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入門(完結篇)

從結果咱們能夠看到,首先是把用戶表給查了,而後根據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();

  輸出結果:
LINQ入門(完結篇)
從log咱們能夠看到這樣就是一條語句查出來數據結果集。注意,這裏演示的是2表關係的查詢,若是當咱們再多出一個表,而這表是與用戶詳細表造成關聯關係的時候那麼,DataLoadoption 就無法解決了一次性查出,而又回到相似上一個樣例分次查出來。例如:
  假設新增一張表(UserDetails2):
  關係以下:
LINQ入門(完結篇)

 生成*.dbml:
LINQ入門(完結篇)
查詢:

// 假設咱們已構造了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();

  查詢結果:
LINQ入門(完結篇)

來自森大科技官方博客
http://www.cnsendblog.com/index.php/?p=175
GPS平臺、網站建設、軟件開發、系統運維,找森大網絡科技!
http://cnsendnet.taobao.com

相關文章
相關標籤/搜索