Entity Framework學習筆記(五)----Linq查詢(2)---貪婪加載

請註明轉載地址:http://www.cnblogs.com/arhat

在上一章中,咱們使用了Linq對Entity Framework進行了一個查詢,可是經過學習咱們卻發現了懶加載給我來的性能上的開銷是很到的,尤爲是在循環中,若是數據量不是不少的狀況下還能夠接受,若是數據量一旦大氣來,那麼這個效率則是影響很是大的。那該怎麼辦呢?其實在Entity Framwork中,除了提供了懶加載技術還提供了一個「貪婪加載」。那麼什麼是貪婪加載呢?從名字上看,就是很是的粗魯的,一次性的吧相關的數據所有查詢出來,雖然在性能上說仍是有點影響的,可是比起在循環中使用懶加載要強了很多了啊。sql

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

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

SQL:學習

select a.* ,b.* from clazz as a left join student as b

on a.CId = b.CId

Linq:spa

DAL.SchoolContext context = new DAL.SchoolContext();

var query = from clazz in context.Clazz

select clazz;

foreach (var clazz in query)

 {

      Console.WriteLine(clazz.CName);

if (clazz.Students != null && clazz.Students.Count > 0)

  {

         foreach(var student in clazz.Students)

        {

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

       }

   }
 }

翻譯SQL:在執行中翻譯的SQL翻譯

wps_clip_image-4720

這裏老魏截圖了,就是由於在循環中使用懶加載而產生了n多個查詢語句,可是code

wps_clip_image-2301

整體上兩個SQL語句:對象

1,查詢出clazz信息的SQLblog

SELECT 

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

    [Extent1].[CName] AS [CName]

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

2,根據懶加載而產生的SQL語句(被重複了N次)ip

exec sp_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

雖然咱們經過懶加載能夠達到咱們想要的效果,可是在效率上是沒法忍受的尤爲是在數據多的狀況下。

那麼Entity Framework也想到了這問題,由於全部的ORM框架都有懶加載,使用起來的確的方便,可是也是在改用的時候用,尤爲在循環中就更不該該使用了。因此這裏呢,老魏有個建議,就是在循環中千萬不要使用懶加載。既然在循環中不能使用懶加載那麼該怎麼辦呢?這就要利用Entity Framework給咱們提供的貪婪加載。下面看如下代碼,而後老魏在來解釋一下。把上面的代碼改成以下的代碼:

DAL.SchoolContext context = new DAL.SchoolContext();

//取消懶加載目的是爲了作實驗看可以一次加載完數據

context.Configuration.LazyLoadingEnabled = false;

var query = from clazz in context.Clazz.Include("Students")

select clazz;

foreach (var clazz in query)

 {

          Console.WriteLine(clazz.CName);

          if (clazz.Students != null && clazz.Students.Count > 0)

          {

              foreach(var student in clazz.Students)

             {

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

              }

         }

}

運行一下,同時監控一下SQL Server的狀態。首先是翻譯的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], 

        CASE WHEN ([Extent2].[SId] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]

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

        LEFT OUTER JOIN [dbo].[Student] AS [Extent2] ON [Extent1].[CId] = [Extent2].[CId]

    )  AS [Project1]

    ORDER BY [Project1].[CId] ASC, [Project1].[C1] ASC

SQL Server狀態:

wps_clip_image-23385

發如今執行的過程當中,循環語句並無的發出額外的指令,只是用來上面翻譯的SQL。可是結果倒是同樣的。

wps_clip_image-2985

無非就是在Linq中加入了一個Include()方法。這個方法就是用來開啓貪婪加載的主要方法。意思是說在加載查詢對象的時候。把查詢對象的關聯數據也查詢出來。其實這裏面是有陷阱的。固然這陷阱值得是Include的參數。顧名思義,和clazz管理的是student對象,那麼在參數就是」Student」。其實否則,由於根據Include參數的含義是說「路徑」。那麼這個路徑是什麼呢?其實就是」導航屬性的名字「。在clazz中有一個導航屬性是Students,則在Include中也要使用這個名字。

固然了,若是你們想的到的話,那麼和Student關聯的對象可以查詢出來呢?答案是確定的,若是關聯屬性有多個則使用」.」來鏈接。好比咱們能夠把代碼改成以下的樣子:

var query = from clazz in context.Clazz.Include("Students.Student_Courses.Courses")

                select clazz;

那咱們在查詢clazz對象的也查出來了student,course的信息。其實看到這裏你們就知道了貪婪加載雖然沒有在循環中那麼的消耗性能,可是一次性查詢的數據是不少的,仍是有影響的,可是沒有懶加載那麼厲害了。

總結一下,若是要在循環中使用數據,請使用貪婪加載,不然使用懶加載。本章就到這裏了。但願你們可以頂一下!謝謝了。

相關文章
相關標籤/搜索