2015-07-12 178 views
37

實體框架中的延遲加載是加載和訪問相關實體時發生的默認現象。然而,急切的加載被稱爲強制加載所有這些關係的做法。我遇到了什麼情況下急切加載比延遲加載更有利的問題。提出這個問題,因爲很明顯,延遲加載對資源更友好,即使我們使用方法,我們仍然可以利用延遲加載行爲。然而,我想可能延遲加載會增加對實際數據庫的請求數量,也許這就是爲什麼有時開發人員使用Inlcude方法強制加載所有關係。例如,當在MVC 5中使用Visual Studio自動腳手架時,在控制器中自動創建的Index方法總是使用Eager Loading,並且在這種情況下,我總是有一個問題,爲什麼微軟默認使用Eager Loading。延遲加載vs預先加載

如果有人向我解釋,在什麼情況下,加載比延遲加載更有利,我們爲什麼要使用它,而對於更加資源友好的Lazy Loading來說,我將不勝感激。

+6

想象一下,您的數據庫上下文將被丟棄並且不再發生延遲加載的情況。然後急切的加載是有益的。 – Transcendent

+1

我看到很多項目因爲性能問題而失敗,這是由於「N + 1選擇」問題導致的,當執行延遲加載時會出現更快的性能問題,所以一定要看看這個問題 –

回答

37

我覺得這是很好的分類,這樣

關係何時使用預先加載

  1. 在您確定用於每一個地方一個一對多的關係的「一面」與主要實體。像一篇文章的用戶屬性。產品的類別屬性。
  2. 通常當關系不太多時,急切的加載將是減少服務器上進一步查詢的良好實踐。

當使用延遲加載

  1. 幾乎在一個一對多關係的每一個「回收側」。像用戶的文章或類別的產品
  2. 你完全知道你不會立即需要財產。

注:像超然說,有可能是處置問題,延遲加載。

+5

我只是試圖回答同樣的問題。當您知道您很少需要使用相關數據時,請使用延遲加載。但是當你知道你會經常需要某些相關數據時,請使用急切的加載。 –

8

延遲加載會產生幾個SQL調用,而Eager加載可能會用一個「更重的」調用(連接/子查詢)加載數據。

例如,如果您的web和sql服務器之間的ping值較高,那麼您將使用Eager加載,而不是使用延遲加載逐個加載相關項。

9

考慮以下情況後

public class Person{ 
    public String Name{get; set;} 
    public String Email {get; set;} 
    public virtual Employer employer {get; set;} 
} 

public List<EF.Person> GetPerson(){ 
    using(EF.DbEntities db = new EF.DbEntities()){ 
     return db.Person.ToList(); 
    } 
} 

現在這個方法被調用時,你不能延遲加載Employer實體了。爲什麼?因爲db對象被丟棄。所以你必須做Person.Include(x=> x.employer)來強制加載。

+2

是的,這是懶惰加載不起作用的示例。另一件事是每次你需要一些數據時創建DbContext是不好的方法。如果你是一個IoC容器,你的DbContext將與Request一起生活(如果是Web應用)。 –

+0

@MiroslavHolec:非常棒,這就是我實際使用Ninject所做的。你剛剛提到的確實非常好。 – Transcendent

0
// Using LINQ and just referencing p.Employer will lazy load 
// I am not at a computer but I know I have lazy loaded in one 
// query with a single query call like below. 
List<Person> persons = new List<Person>(); 
using(MyDbContext dbContext = new MyDbContext()) 
{ 
    persons = (
     from p in dbcontext.Persons 
     select new Person{ 
      Name = p.Name, 
      Email = p.Email, 
      Employer = p.Employer 
     }).ToList(); 
} 
+0

儘管此代碼片段可能會解決此問題,但[包括解釋](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers)確實有助於提高帖子的質量。請記住,您將來會爲讀者回答問題,而這些人可能不知道您的代碼建議的原因。 – Arefly

+0

這個答案根本沒有解決OP的問題。 OP不問如何做「懶加載」,他問的是「何時使用'懶加載'和何時加載'' – Mischa

5

預先加載: 預先加載幫助您一次加載所有需要的實體。即相關對象(子對象) 會自動加載其父對象。

何時使用:

  1. 使用預先加載時,關係並不太大。 因此,Eager Loading是減少服務器上進一步查詢的良好做法。
  2. 使用Eager載入,當你確定你將使用與主要實體相關的實體。

延遲加載: 在延遲加載的情況下,相關對象(子對象)都不會自動 與它的父對象,直到他們被要求加載。 默認情況下,LINQ支持延遲加載。

何時使用:

  1. 使用延遲加載,當您使用一個一對多的集合。
  2. 如果您確定沒有立即使用相關實體,請使用延遲加載。

注:實體框架支持三種方法來加載相關的數據 - 預先加載,延遲加載和明確的裝載。