EF中的貪婪加載和延遲加載(懶加載)

在上一章中,我們使用了Linq對Entity Framework進行了一個查詢,但是通過學習我們卻發(fā)現(xiàn)了懶加載給我來的性能上的開銷是很到的,尤其是在循環(huán)中,如果數(shù)據(jù)量不是很多的情況下還可以接受,如果數(shù)據(jù)量一旦大氣來,那么這個效率則是影響非常大的。那該怎么辦呢?其實在Entity Framwork中,除了提供了懶加載技術還提供了一個“貪婪加載”。那么什么是貪婪加載呢?從名字上看,就是非常的粗魯?shù)?,一次性的吧相關的數(shù)據(jù)全部查詢出來,雖然在性能上說還是有點影響的,但是比起在循環(huán)中使用懶加載要強了不少了啊。

下面呢,老魏先不說懶加載的知識,把上一張遺留的一個查詢給家說一下,順便以這個例子和貪婪加載做一下對比。

Demo3:查詢班級的信息,還要得到此班級中的學生。

SQL:

selecta.*,b.*fromclazzasaleftjoinstudentas bona.CId=b.CId

Linq:

DAL.SchoolContext context =new DAL.SchoolContext();varquery =fromclazzin context.Clazzselect clazz;foreach(varclazzin query)

{

? ? ? Console.WriteLine(clazz.CName);if(clazz.Students !=null&& clazz.Students.Count >0)

? {? ? ? ? foreach(varstudentin clazz.Students)

? ? ? ? {

? ? ? ? ? Console.WriteLine("---該班的學生:"+ student.SName);

? ? ? }

? }

}

翻譯SQL:在執(zhí)行中翻譯的SQL

這里老魏截圖了,就是因為在循環(huán)中使用懶加載而產(chǎn)生了n多個查詢語句,但是

總體上兩個SQL語句:

1,查詢出clazz信息的SQL

SELECT[Extent1].[CId]AS[CId],

? ? [Extent1].[CName]AS[CName]FROM[dbo].[Clazz]AS[Extent1]

2,根據(jù)懶加載而產(chǎn)生的SQL語句(被重復了N次)

execsp_executesql N'SELECT

? ? [Extent1].[SId] AS [SId],

? ? [Extent1].[SName] AS [SName],

? ? [Extent1].[SAge] AS [SAge],

? ? [Extent1].[SMail] AS [SMail],

? ? [Extent1].[CId] AS [CId]

? ? FROM [dbo].[Student] AS [Extent1]

? ? WHERE [Extent1].[CId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=2

雖然我們通過懶加載可以達到我們想要的效果,但是在效率上是無法忍受的尤其是在數(shù)據(jù)多的情況下。

那么Entity Framework也想到了這問題,因為所有的ORM框架都有懶加載,使用起來的確的方便,但是也是在改用的時候用,尤其在循環(huán)中就更不應該使用了。所以這里呢,老魏有個建議,就是在循環(huán)中千萬不要使用懶加載。既然在循環(huán)中不能使用懶加載那么該怎么辦呢?這就要利用Entity Framework給我們提供的貪婪加載。下面看以下代碼,然后老魏在來解釋一下。把上面的代碼改為如下的代碼:

DAL.SchoolContext context =new DAL.SchoolContext();//取消懶加載目的是為了做實驗看能夠一次加載完數(shù)據(jù)context.Configuration.LazyLoadingEnabled =false;varquery =fromclazzincontext.Clazz.Include("Students")select clazz;foreach(varclazzin query)

{

? ? ? ? ? Console.WriteLine(clazz.CName);? ? ? ? ? if(clazz.Students !=null&& clazz.Students.Count >0)

? ? ? ? ? {? ? ? ? ? ? ? foreach(varstudentin clazz.Students)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? Console.WriteLine("---該班的學生:"+ student.SName);

? ? ? ? ? ? ? }

? ? ? ? }

}

運行一下,同時監(jiān)控一下SQL Server的狀態(tài)。首先是翻譯的SQL:

SELECT[Project1].[CId]AS[CId],

? ? [Project1].[CName]AS[CName],

? ? [Project1].[C1]AS[C1],

? ? [Project1].[SId]AS[SId],

? ? [Project1].[SName]AS[SName],

? ? [Project1].[SAge]AS[SAge],

? ? [Project1].[SMail]AS[SMail],

? ? [Project1].[CId1]AS[CId1]FROM(SELECT[Extent1].[CId]AS[CId],

? ? ? ? [Extent1].[CName]AS[CName],

? ? ? ? [Extent2].[SId]AS[SId],

? ? ? ? [Extent2].[SName]AS[SName],

? ? ? ? [Extent2].[SAge]AS[SAge],

? ? ? ? [Extent2].[SMail]AS[SMail],

? ? ? ? [Extent2].[CId]AS[CId1],

? ? ? ? CASEWHEN([Extent2].[SId]ISNULL)THENCAST(NULLASint)ELSE1ENDAS[C1]FROM[dbo].[Clazz]AS[Extent1]LEFTOUTERJOIN[dbo].[Student]AS[Extent2]ON[Extent1].[CId]=[Extent2].[CId]? ? )? AS[Project1]ORDERBY[Project1].[CId]ASC,[Project1].[C1]ASC

SQL Server狀態(tài):

發(fā)現(xiàn)在執(zhí)行的過程中,循環(huán)語句并沒有的發(fā)出額外的指令,只是用來上面翻譯的SQL。但是結果卻是一樣的。

無非就是在Linq中加入了一個Include()方法。這個方法就是用來開啟貪婪加載的主要方法。意思是說在加載查詢對象的時候。把查詢對象的關聯(lián)數(shù)據(jù)也查詢出來。其實這里面是有陷阱的。當然這陷阱值得是Include的參數(shù)。顧名思義,和clazz管理的是student對象,那么在參數(shù)就是”Student”。其實不然,因為根據(jù)Include參數(shù)的含義是說“路徑”。那么這個路徑是什么呢?其實就是”導航屬性的名字“。在clazz中有一個導航屬性是Students,則在Include中也要使用這個名字。

當然了,如果大家想的到的話,那么和Student關聯(lián)的對象能夠查詢出來呢?答案是肯定的,如果關聯(lián)屬性有多個則使用”.”來連接。比如我們可以把代碼改為如下的樣子:

varquery =fromclazzincontext.Clazz.Include("Students.Student_Courses.Courses")? ? ? ? ? ? ? ? selectclazz;

那我們在查詢clazz對象的也查出來了student,course的信息。其實看到這里大家就知道了貪婪加載雖然沒有在循環(huán)中那么的消耗性能,但是一次性查詢的數(shù)據(jù)是很多的,還是有影響的,但是沒有懶加載那么厲害了。

總結一下,如果要在循環(huán)中使用數(shù)據(jù),請使用貪婪加載,否則使用懶加載。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 希望對大家面試有幫助,很經(jīng)典的幾道題,大家有興趣的話,歡迎大家加群討論,QQ群號:295383988 問題及描述:...
    hc愛編程閱讀 1,949評論 0 12
  • Student(Sid,Sname,Sage,Ssex) 學生表Course(Cid,Cname,Tid) 課程表...
    小爐爐閱讀 1,536評論 0 0
  • 一、多表查詢 --編寫多表查詢語句的一般過程 --(1)、分析句子要涉及到哪些表 --(2)、對應的表中要查詢哪些...
    __71db閱讀 1,906評論 0 6
  • 說明:以下五十個語句都按照測試數(shù)據(jù)進行過測試,最好每次只單獨運行一個語句。 問題及描述: --1.學生表 Stud...
    lijun_m閱讀 1,375評論 0 1
  • 最常見的三種模式 1.資本增值 常見形式有保險、企業(yè)理財、股票證券等。 2.電子交易 如微信支付、支付寶支付,產(chǎn)生...
    Jim花閱讀 124評論 0 0

友情鏈接更多精彩內容