国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

LINQ to SQL實(shí)現(xiàn)數(shù)據(jù)訪問通用基類

開發(fā) 后端 數(shù)據(jù)庫運(yùn)維
LINQ to SQL讓人著迷,在.Net應(yīng)用程序當(dāng)中,.它提供了一種安全,強(qiáng)大和非常靈活的方式執(zhí)行數(shù)據(jù)訪問,在當(dāng)前微軟傳道者介紹上看,很容易上手。

不幸的是,當(dāng)你對LINQ進(jìn)行仔細(xì)研究后,我發(fā)現(xiàn)在多層架構(gòu)中使用LINQ的并不是十分容易。

本文介紹用LINQ to SQL實(shí)現(xiàn)數(shù)據(jù)層的典型的問題點(diǎn) ,并提供了一個簡單,方便和靈活的方式來克服它們。

本文附帶的LINQ to SQL 實(shí)現(xiàn)數(shù)據(jù)訪問通用類有以下的特點(diǎn):

實(shí)現(xiàn)了存儲庫模式,你可以用不到10行代碼執(zhí)行LINQ實(shí)體類型的CRUD (Create, Update, Delete)操作。
無縫協(xié)作,支持LINQ斷開模式(Disconnected LINQ Mode)。
在單一數(shù)據(jù)庫和LINQ實(shí)體間支持透明的數(shù)據(jù)庫更新和數(shù)據(jù)加載。
提供為一種方便的功能,在調(diào)試你的應(yīng)用程尋時候,它把所有執(zhí)行的SQL語句輸出控制臺。
本文將假定您對LINQ to SQL (也稱為DLINQ )有一個基本的了解并如何使用它。否則,,,回到此網(wǎng)頁,看看本教程入門系列,如何在多層次應(yīng)用中使用LINQ to SQL。

存在的問題

如果您只是在你的UI層直接用LinqToDataSource對象銜接數(shù)據(jù)庫,那LINQ to SQL太容易使用了。但是,這種做法不完全面向?qū)ο螅?dāng)然也不是一個可取的架構(gòu),除非你是為了快速編碼和臟亂的應(yīng)用程序,并且最終沒有去擴(kuò)展的它打算。

相反,大多數(shù)開發(fā)人員把它們的應(yīng)用程序劃分成若干層,如下:

數(shù)據(jù)訪問層(Data Access Layer)

業(yè)務(wù)層 (Business Layer)

用戶界面層(UI Layer)

這就是所謂的多層數(shù)據(jù)庫應(yīng)用程序設(shè)計(jì)。LINQ to SQL將用于數(shù)據(jù)訪問層。

LINQ to SQL的問題是-盡管它的許多優(yōu)點(diǎn)-但是如果要實(shí)現(xiàn)數(shù)據(jù)層并不是很簡單。

請看下面的數(shù)據(jù)庫模式(database schema):

一旦你要加載和保存LINQ實(shí)體到同一個的數(shù)據(jù)上下文實(shí)例(data context instance)(這就是所謂“連接模式”),用LINQ實(shí)現(xiàn)數(shù)據(jù)層非常直接。

例如,讓我們從數(shù)據(jù)庫中獲取實(shí)體編號為1的客戶,改變屬性first name為“Homer”后在重新儲存到數(shù)據(jù)庫中。在一個多層數(shù)據(jù)庫應(yīng)用程序中,在UI或業(yè)務(wù)層的某個地方的代碼可能看起來就像這樣:

view plaincopy to clipboardprint?
1.         
2.       //create a new repository instance   
3.       CustomersRepository customersRepository = new CustomersRepository();   
4.       //load a customer instance and change it's FirstName;   
5.       Customer customer = customersRepository.Load(2);   
6.       customer.FirstName = "Homer";   
7.       //commmit customer to database   
8.       customersRepository.Save(customer);  
 

最簡單的方法來實(shí)現(xiàn)上面使用到的數(shù)據(jù)層加載和保存功能是:

view plaincopy to clipboardprint?
1.         
2.       static DataClassesDataContext context=new DataClassesDataContext();   
3.       public Customer Load(int CustomerID)   
4.       {   
5.       return context.Customers.Single(c => c.ID == CustomerID);   
6.       }   
7.       public void Save(Customer toSave)   
8.       {   
9.       context.SubmitChanges();   
10.   }  

這種方法是使用連接LINQ模式:數(shù)據(jù)上下文(data context)在當(dāng)前作用域一直有效(譯者注:一直保持連接狀態(tài)),所以在把實(shí)體保存到數(shù)據(jù)庫的時候,它總是可以重復(fù)使用。其中仍然連接到它。

當(dāng)然,這種做法方便并且在上述的單個例子中能運(yùn)行,但它存在嚴(yán)重的并發(fā)問題,因?yàn)橐粋€數(shù)據(jù)庫方面是用于所有數(shù)據(jù)庫操作。

當(dāng)調(diào)用方法Save(),bmitChanges提交的不僅僅是當(dāng)前Save 方法參數(shù)相關(guān)的LINQ實(shí)體,還包括所有改變了的實(shí)體。

但是及時把這個缺陷考慮在一邊,使用LINQ在一個多層ASP.NET應(yīng)用程序中,您還不能以相同方式實(shí)現(xiàn)數(shù)據(jù)層。首先,可能要求是這樣,在一個頁面請求中,LINQ實(shí)體被加載,然后在下一個頁面請求中,它更新并儲存到數(shù)據(jù)庫中的。.同時,您的原始數(shù)據(jù)上下文在當(dāng)前作用域內(nèi)已經(jīng)無效的(譯者住:HTTP協(xié)議是無狀態(tài)的),造成的您的LINQ實(shí)體游離。

還有許多其他情況下你需要使用斷開LINQ模式:例如您實(shí)現(xiàn)的數(shù)據(jù)庫層可能要作為一個Web服務(wù),提交(commit)以前序列化LINQ實(shí)體到數(shù)據(jù)庫等等。

用斷開模式的LINQ to SQL實(shí)現(xiàn)數(shù)據(jù)訪問層

所以,在斷開的LINQ模式下,我們?nèi)绾螌?shí)現(xiàn)數(shù)據(jù)層的Save( )方法?

我們必須

Detach the entity from the old data context從舊的數(shù)據(jù)上下文中分離實(shí)體

Create a new data context創(chuàng)建一個新的數(shù)據(jù)上下文

Attach the entity to the new context附加實(shí)體到新的數(shù)據(jù)上下文

Submit changes提交更改

在源代碼,它看起來像這樣:

 view plaincopy to clipboardprint?
1.         
2.       public Customer Load(int CustomerID)   
3.       {   
4.       DataClassesDataContext context = new DataClassesDataContext();   
5.       return context.Customers.Single(c => c.ID == CustomerID);   
6.       }   
7.         
8.       public void Save(Customer toSave)   
9.       {   
10.   //the old data context is no more, we need to create a new one   
11.   DataClassesDataContext context = new DataClassesDataContext();   
12.   //serialize and deserialize the entity to detach it from the   
13.   //old data context. This is not part of .NET, I am calling   
14.   //my own code here   
15.   toSave = EntityDetacher.Detach(toSave);   
16.   //is the entity new or just updated?   
17.   //ID is the customer table's identity column, so new entities should   
18.   //have an ID == 0   
19.   if (toSave.ID == 0)   
20.   {   
21.   //insert entity into Customers table   
22.   context.Customers.InsertOnSubmit(toSave);   
23.   }   
24.   else  
25.   {   
26.   //attach entity to Customers table and mark it as "changed"   
27.   context.Customers.Attach(toSave, true);   
28.   }   
29.   }  
 

現(xiàn)在只要你喜歡,您可以加載修改任意多實(shí)體,并且只提交他們一部分到數(shù)據(jù)庫。但由于使用斷開的LINQ ,這個程序并不會感知到LINQ實(shí)體之間的關(guān)系。

例如,假設(shè)在業(yè)務(wù)層或用戶界面層您要做到以下幾點(diǎn):

view plaincopy to clipboardprint?
1.         
2.       //load currently selected customer from database   
3.       Customer customer = new CustomersRepository().Load(1);   
4.       //change the customer's first name   
5.       customer.FirstName = "Homer";   
6.       //add a new bill with two billingitems to the customer   
7.       Bill newbill = new Bill   
8.       {   
9.       Date = DateTime.Now,   
10.   BillingItems =   
11.   {   
12.   new BillingItem(){ItemPrice=10, NumItems=2},   
13.   new BillingItem(){ItemPrice=15, NumItems=1}   
14.   }   
15.   };   
16.   customer.Bills.Add(newbill);   
17.   //create a new provider to simulate new ASP.NET page request   
18.   //save the customer   
19.   new CustomersRepository().Save(customer);  
 

這個斷開模式下,上述Save( )方法將提交變更到FirstName列,但是忽略了new bill和billing items。為了做到這一點(diǎn),我們還需要附加或插入遞歸所有相關(guān)的子實(shí)體(child entities):

 

view plaincopy to clipboardprint?

1.        

2.       public void Save(Customer toSave)  

3.       {  

4.       //the old data context is no more, we need to create a new one  

5.       DataClassesDataContext context = new DataClassesDataContext();  

6.       //serialize and deserialize the entity to detach it from the  

7.       //old data context. This is not part of .NET, I am calling  

8.       //my own code here  

9.       toSave = EntityDetacher.Detach(toSave);  

10.   //is the entity new or just updated?  

11.   //ID is the customer table's identity column, so new entities should  

12.   //have an ID == 0  

13.   if (toSave.ID == 0)  

14.   {  

15.   //insert entity into Customers table  

16.   context.Customers.InsertOnSubmit(toSave);  

17.   }  

18.   else 

19.   {  

20.   //attach entity to Customers table and mark it as "changed"  

21.   context.Customers.Attach(toSave, true);  

22.   }  

23.   //attach or save all "bill" child entities  

24.   foreach (Bill bill in toSave.Bills)  

25.   {  

26.   if (bill.ID == 0)  

27.   {  

28.   context.Bills.InsertOnSubmit(bill);  

29.   }  

30.   else 

31.    

32.   {  

33.   context.Bills.Attach(bill, true);  

34.   }  

35.   //attach or save all "BillingItem" child entities  

36.   foreach (BillingItem billingitem in bill.BillingItems)  

37.   {  

38.   if (bill.ID == 0)  

39.   {  

40.   context.BillingItems.InsertOnSubmit(billingitem);  

41.   }  

42.   else 

43.   {  

44.   context.BillingItems.Attach(billingitem, true);  

45.   }  

46.   }  

47.   }  

48.   } 

不是很復(fù)雜,但很多打字(譯者注:翻譯不是很難,但要一句句的理解,還要打很多字)。并且這只是支持一個微不足道的database scheme和一個單一的實(shí)體類型。.想象一下,如果實(shí)現(xiàn)數(shù)據(jù)庫層有幾十個實(shí)體類型與幾十個外鍵關(guān)系,在這個數(shù)據(jù)存儲類中,你將要為每一個LINQ實(shí)體寫幾十套foreach循環(huán),這不僅是單調(diào)乏味,而且還容易出錯。.當(dāng)你添加新的表,你必須添加幾十foreach循環(huán)。

如何避免這些問題

在相當(dāng)多的在線調(diào)研后,我實(shí)現(xiàn)了一個RepositoryBase類,使用他您可以快速實(shí)現(xiàn)您的數(shù)據(jù)層,所示為測試通過的例子。 首先,用對象關(guān)系映射器(譯者注:Visual Studio自帶工具)來產(chǎn)生序列化的LINQ實(shí)體:在Visual Studio中打開dbml文件,在空白區(qū)域某處左鍵單擊,彈出屬性窗口,設(shè)置“Serialization Mode屬性”為“Unidirectional”。

 

現(xiàn)在您可以繼承RepositoryBase實(shí)現(xiàn)您自己的Repository:

view plaincopy to clipboardprint?
1.         
2.       public void Save(Customer toSave)   
3.       {   
4.       //the old data context is no more, we need to create a new one   
5.       DataClassesDataContext context = new DataClassesDataContext();   
6.       //serialize and deserialize the entity to detach it from the   
7.       //old data context. This is not part of .NET, I am calling   
8.       //my own code here   
9.       toSave = EntityDetacher.Detach(toSave);   
10.   //is the entity new or just updated?   
11.   //ID is the customer table's identity column, so new entities should   
12.   //have an ID == 0   
13.   if (toSave.ID == 0)   
14.   {   
15.   //insert entity into Customers table   
16.   context.Customers.InsertOnSubmit(toSave);   
17.   }   
18.   else  
19.   {   
20.   //attach entity to Customers table and mark it as "changed"   
21.   context.Customers.Attach(toSave, true);   
22.   }   
23.   //attach or save all "bill" child entities   
24.   foreach (Bill bill in toSave.Bills)   
25.   {   
26.   if (bill.ID == 0)   
27.   {   
28.   context.Bills.InsertOnSubmit(bill);   
29.   }   
30.   else  
31.     
32.   {   
33.   context.Bills.Attach(bill, true);   
34.   }   
35.   //attach or save all "BillingItem" child entities   
36.   foreach (BillingItem billingitem in bill.BillingItems)   
37.   {   
38.   if (bill.ID == 0)   
39.   {   
40.   context.BillingItems.InsertOnSubmit(billingitem);   
41.   }   
42.   else  
43.   {   
44.   context.BillingItems.Attach(billingitem, true);   
45.   }   
46.   }   
47.   }   
48.   }  

您的每一個實(shí)體的類型都照這樣做,你就擁有了一個工作在斷開模式下無縫數(shù)據(jù)層。您繼承Repository的類自動執(zhí)行下列方法:

 

 


作為錦上添花的功能,在應(yīng)用程序調(diào)試的過程中,你還可以通過輸出控制臺看到執(zhí)行對數(shù)據(jù)庫的操作的SQL命令。這多虧了被用于RepositoryBase的SQL調(diào)試輸出的Kris Vandermotten 方便的DebuggerWriter組件(譯者注:外國人就是紳士)!

天下有沒有免費(fèi)的午餐...

當(dāng)前的加載(Load)操作中,沒有任何顯著的性能損失,但是當(dāng)你調(diào)用Save or Delete方法時候,幕后用到一點(diǎn)反射(reflection)操作。

對于絕大多數(shù)的數(shù)據(jù)訪問層(DAL)需求,在你的應(yīng)用程序當(dāng)中,這可能并沒有顯著的的影響。 但是,如果您正在執(zhí)行大量的更新/插入/刪除操作,特別是大量的包含嵌套的實(shí)體,那么您可能需要自己寫代碼替代Repository的Save / Delete方法。.所有Save / Delete方法都是虛方法(virtual),因此您可以輕易重寫(override)他們。

另外請注意, RepositoryBase不支循環(huán)依賴(circular dependencies)的遞遞歸save 或者 delete操作。

結(jié)論

本文將和包括源代碼提供了一個簡單,方便和可擴(kuò)展的方式實(shí)現(xiàn)您的多層LINQ數(shù)據(jù)層CRUD(譯者注:增,刪,改,查)的方法。.它利用斷開模式,并支持保存(saving)和加載(loading)嵌套子實(shí)體(child entities).在Save 和Delete(譯者注:原文為Load,可能原作者筆誤)操作時候有一個小小的性能損失,但在性能至關(guān)重要的應(yīng)用中,您可以重寫這些Repositories類的Save和Delete。

對于一切,你安心上路,只需幾行代碼。 

【編輯推薦】

  1. 使用LINQ to XML來查詢XML
  2. SQL連接中加條件查詢的LINQ表達(dá)式寫法
  3. .NET開發(fā)工具LINQ框架設(shè)計(jì)指南
責(zé)任編輯:彭凡 來源: 博客園
相關(guān)推薦

2009-09-15 10:02:44

Linq to SQL

2009-09-09 16:45:29

Linq調(diào)用數(shù)據(jù)訪問服

2009-12-02 10:33:34

LINQ to SQL

2009-09-15 17:07:24

Linq To SQL

2009-09-14 09:46:00

LINQ to SQL

2009-12-23 09:04:41

LINQ通用分頁

2009-09-10 10:09:46

LINQ to SQL

2009-09-14 10:12:11

LINQ to SQL

2009-09-14 13:17:51

LINQ to SQLLINQ to SQL

2009-09-18 14:07:51

LINQ to SQL

2009-09-18 15:19:19

LINQ to SQL

2009-09-07 16:13:14

LINQ to SQL

2009-06-08 09:22:07

數(shù)據(jù)訪問優(yōu)化SQL Server

2011-03-29 09:15:28

通用數(shù)據(jù)訪問層

2009-09-18 14:25:36

LINQ to SQL

2009-09-08 14:45:24

Linq to SQL支持SQL Serve

2009-09-16 10:27:35

LINQ Custom

2009-09-11 12:08:09

Linq to SQL

2009-09-11 12:13:40

LINQ to SQL

2009-09-08 13:16:01

Linq to SQL
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

中文字幕 久热精品 视频在线| 国产成人精选| 日韩一区二区三区精品 | 热99在线观看| 在线视频中文字幕第一页| 九九精品在线| 亚洲丝袜美腿综合| 日本不卡免费高清视频| av免费中文字幕| av一卡二卡| 色综合久久精品| 日本丰满大乳奶| 九色丨蝌蚪丨成人| 欧美日韩国产系列| 日本精品一区二区三区四区| 免费精品国产| 欧美日韩第一区日日骚| 在线观看日本一区| 亚洲成人一品| 91精品在线麻豆| 成人软件网18免费视频| 欧美国产在线电影| 奇米影视四色在线| 丁香五精品蜜臀久久久久99网站 | 首页国产精品| 国产精品一国产精品最新章节| 99在线精品视频在线观看| 日产精品高清视频免费| aa级大片欧美| 在线观看你懂得| 亚洲国产日韩一区| 国产精品手机在线播放 | caoporen人人| 国产不卡视频在线观看| 久久久久久久久四区三区| 欧美私人啪啪vps| 欧美一区二区三区在线免费观看| 日韩在线高清| 欧美女子与性| 2025韩国大尺度电影| 欧美一级高清免费播放| 性网站在线观看| 欧美大片在线看免费观看| 97视频热人人精品免费| 在线观看欧美日韩国产| 黄色在线成人| 国产在线免费观看| 欧美一区二区三区不卡| 国产精品久久久亚洲一区| 久久精品久久久精品美女| 成熟丰满熟妇高潮xxxxx视频| 美女呻吟一区| 欧美激情精品久久久久久免费印度 | 不卡中文一二三区| 亚洲一区综合| 中文字幕免费精品一区| 久久精品国产精品亚洲综合| 国产极品精品在线观看| 亚洲欧洲av一区二区三区久久| 九色在线视频| 黄页视频在线免费观看| 欧美色图在线视频| 青春草在线免费视频| 精品国产一区二区在线| 欧美一区二区三区高清视频| 精品国产一区二区三区四区精华| 97精品久久久久中文字幕| 中文字幕视频在线观看| 亚洲免费视频一区二区| 国产日产一区| 在线观看日韩羞羞视频| 亚洲男同性视频| 1024在线看片你懂得| 欧美亚洲在线视频| 青青草一区二区三区| www.日本视频| 精品在线观看国产| 亚洲影视一区二区三区| 黄色免费观看视频网站| 精品视频一区三区九区| 911亚洲精品| 神马一区二区影院| 亚洲一区在线看| 久久精品超碰| 玛丽玛丽电影原版免费观看1977 | 成人丝袜高跟foot| 在线免费观看黄色片| 亚洲欧美日韩中文在线| 日韩中文字幕高清在线观看| 五月天激情图片| 欧美性猛交xxxx乱大交| 偷拍精品精品一区二区三区| 国产精品免费视频一区二区| 国产精品成人免费| 春暖花开亚洲一区二区三区| 国产精品一区二区三区免费| 亚洲日本护士毛茸茸| 国产91在线播放精品| 欧美日韩精品中文字幕一区二区| 一区二区三区日韩精品| www 久久久| 日本三级福利片| 91精品一区二区三区在线观看| 大片网站久久| 99爱免费视频| 丝袜亚洲欧美日韩综合| 麻豆传媒一区二区三区| 成年人视频网站在线| 国产精品欧美激情在线播放| 国产欧美日本一区二区三区| 久久91视频| 日本香蕉视频在线观看| 亚洲精品一区在线观看| 亚洲视频成人| 伊人免费在线| 国产成人精品日本亚洲11 | 在线观看的毛片| 国产亚洲精品高潮| 精品一区二区三区久久久| 日本最黄一级片免费在线| 亚洲最大成人免费视频| 亚洲成人av一区二区| 欧美变态挠脚心| 成人eeuss影院在线观看| 欧美精品xxx| 国产精品天天看| 精品自拍偷拍| 国产va在线| 国产精品丝袜高跟| 亚洲国产综合人成综合网站| 国产欧美日韩| 在线欧美成人| 99c视频在线| 欧美精品亚洲二区| 日韩av午夜在线观看| 丰满大乳少妇在线观看网站 | 欧美视频四区| 黄色网址免费在线观看| 麻豆精品传媒视频| 日韩欧美www| 激情综合色综合久久综合| 樱花草涩涩www在线播放| 小说区图片区图片区另类灬| 亚洲韩国日本中文字幕| 成人黄色一级视频| 日本精品视频| 男人天堂2020| 亚洲精品欧美日韩专区| 制服丝袜亚洲播放| 国产成人免费高清| 91国内精品| 污污软件在线观看| 日本在线观看一区二区三区| 亚洲香蕉成视频在线观看| 久久久久久麻豆| 成人综合专区| 天天色天天射天天综合网| 伊人久久在线观看| 色综合久久88| 亚洲妇熟xx妇色黄| 香蕉久久国产| 天堂久久一区| 国产美女极品在线| 欧美日本亚洲| 另类专区欧美制服同性| 午夜久久久影院| 美女精品在线| 日韩一级视频| 老司机色在线视频| 日本成人三级电影网站| 久久影院在线观看| 日韩欧美极品在线观看| 久久成人av少妇免费| 国产另类在线| 国产视频中文字幕在线观看| 日韩欧美一区三区| 51国偷自产一区二区三区的来源| 亚洲激情免费观看| 亚洲乱码日产精品bd| 视频在线观看91| 成人中文字幕视频| 毛片免费不卡| 在线观看高清免费视频| 国产精品一区二区三区精品| 视频直播国产精品| 欧美在线高清视频| 91丨国产丨九色丨pron| 亚洲性色视频| jizz国产精品| 伊人影院在线视频| 可播放的18gay1069| 欧美日韩在线免费观看视频| 国产精品久久久精品| 日韩国产高清视频在线| 婷婷综合另类小说色区| 成年人国产精品| 国产日韩专区| 精品一区二区三区在线| 三上悠亚国产精品一区二区三区| 全色精品综合影院|