LINQ-to-SQL那點事~關(guan)于延時加載的性能,微(wei)軟給出了(le)不錯的解決(jue)方案
LINQ-to-SQL雖然已經屬于過去事了,但由于歷史原因,還是要關注一下它,呵呵,當微軟推出linq to sql之后,最吸引開發者的地方可能就是可視化的數據模型,靈活可控的分部方法及神神秘秘的延時加載了,呵呵!今(jin)天主(zhu)要(yao)再總結(jie)一個linq to sql中的延時加載!
對于數據上(shang)下文DataContext來說,它有一(yi)個屬性叫做DeferredLoadingEnabled,它的(de)(de)默認值為(wei)(wei)true,意思是(shi)開啟(qi)模型(xing)的(de)(de)延(yan)時(shi)加載(zai)功能,例如:當(dang)你有一(yi)個對象(xiang)Order_info,它有關(guan)系表Order_Detail,它們之間為(wei)(wei)一(yi)對多的(de)(de)關(guan)系,這在(zai)dbml模型(xing)中用(yong)(yong)EntitySet<T>來表示,意為(wei)(wei)實體的(de)(de)集(ji)合(he)。而開啟(qi)模型(xing)的(de)(de)延(yan)時(shi)加載(zai)功能時(shi),只要你查詢出Order_Info后,如果在(zai)前臺使(shi)用(yong)(yong)到了Order_Detail,系統就會將Order_Detail的(de)(de)相關(guan)數據也查詢出來,聽(ting)上(shang)去(qu)不錯,看代碼:
@foreach (var item in Model) { <p> @item.OrderID @item.CreateDate </p> if (item.Order_Detail.Count > 0) { foreach (var detail in item.Order_Detail) { <p style="margin: 10px;">@detail.OrderID @detail.ProductName</p> } } }
產生的SQL代碼:
注意,當前臺對Order_Detail有需要時,系統會產生查詢Order_Detail的代碼,如果你的10條Order_Info記錄,那么,系統會向SQLSERVER發送10條語句
,這讓我(wo)們感覺到了一點壞味(wei)道,沒(mei)錯,使用(yong)延時加載不(bu)(bu)但沒(mei)有提(ti)高性能,反爾(er)加大了數據庫的(de)交(jiao)互,事(shi)實上,我(wo)可(ke)能不(bu)(bu)是微軟的(de)本(ben)意,可(ke)能是我(wo)們誤會(hui)了DeferredLoadingEnabled的(de)用(yong)意,呵(he)呵(he)!
DeferredLoadingEnabled使用場合:對于單條記錄可以使用,對于集合對象不應該使用它
Linq To Sql對于集合對象的(de)導航屬性(xing)進行延時加載,提供了自(zi)己的(de)解決方案
小(xiao)插曲(qu),一(yi)般我(wo)們(men)(men)建(jian)立(li)(li)DBML模(mo)型(xing)(xing)后,如(ru)果希望(wang)改(gai)(gai)它的(de)代(dai)碼(ma)部分我(wo)們(men)(men)一(yi)般不會在(zai)原文(wen)(wen)(wen)(wen)件(jian)(jian)上改(gai)(gai),因為重新生成數(shu)據模(mo)型(xing)(xing)后,你改(gai)(gai)的(de)代(dai)碼(ma)就(jiu)被(bei)覆蓋了(le)(le),而我(wo)們(men)(men)的(de)做法(fa)(fa)是(shi)新建(jian)一(yi)個(ge)(ge)類文(wen)(wen)(wen)(wen)件(jian)(jian),它與DBML模(mo)型(xing)(xing)文(wen)(wen)(wen)(wen)件(jian)(jian)的(de)數(shu)據上下文(wen)(wen)(wen)(wen)對(dui)象同名(ming)(微軟(ruan)為我(wo)們(men)(men)建(jian)立(li)(li)的(de)上下文(wen)(wen)(wen)(wen)類是(shi)partial的(de),人家已經為咱們(men)(men)預留(liu)出接口了(le)(le),呵呵),如(ru)果希望(wang)在(zai)數(shu)據上下文(wen)(wen)(wen)(wen)被(bei)建(jian)立(li)(li)時執行代(dai)碼(ma),可(ke)以在(zai)分部方法(fa)(fa)OnCreate里(li)作文(wen)(wen)(wen)(wen)章(注意默認構造方法(fa)(fa)已經被(bei)原類占用,所以你的(de)分部類不能再定義一(yi)個(ge)(ge)空構造方法(fa)(fa)了(le)(le),呵呵)。
DataLoadOptions 對象為我們(men)提(ti)供了立即(ji)加(jia)載模(mo)式,它(ta)(ta)所產生(sheng)的SQL語句(ju)是我們(men)可以接受的,但它(ta)(ta)不會按需(xu)查詢了,即(ji)將order_info和(he)order_detail進(jin)行join
查(cha)詢并(bing)直接返回數(shu)據,呵(he)呵(he)。
這種(zhong)方法只(zhi)在分部方法OnCreate中定義即可,你(ni)的(de)DAL實現(xian)層,BLL業務組合(he)層,WEB展現(xian)層的(de)代碼都不用調整,呵(he)呵(he)。
partial void OnCreated() { // this.DeferredLoadingEnabled = false;//關閉(bi)延時(shi)加載 #region 優化后的延時加載,對某個對象進行延時加載 DataLoadOptions dl = new DataLoadOptions(); dl.LoadWith<Order_Info>(p => p.Order_Detail); this.LoadOptions = dl; #endregion }
而這種立(li)即加載所(suo)產生的SQL語句是我們(men)可(ke)以接受的,看圖:
它(ta)解釋成(cheng)的SQL語(yu)句也是我們(men)熟(shu)悉(xi)的,看代碼:
SELECT [t0].[OrderID], [t0].[UserID], [t0].[CreateDate], [t1].[OrderDetailID], [t1].[OrderID] AS [OrderID2], [t1].[ProductID], [t1].[ProductName], ( SELECT COUNT(*) FROM [dbo].[Order_Detail] AS [t2] WHERE [t2].[OrderID] = [t0].[OrderID] ) AS [value] FROM [dbo].[Order_Info] AS [t0] LEFT OUTER JOIN [dbo].[Order_Detail] AS [t1] ON [t1].[OrderID] = [t0].[OrderID] ORDER BY [t0].[OrderID], [t1].[OrderDetailID]
恩,看來(lai)linq to sql知所以性能低(di)下,不是它(ta)(ta)本身的問題(ti),而是我們對它(ta)(ta)不夠了解呀,呵呵!