2017-03-27 69 views
2

我已禁用延遲加載,但實體是從數據庫中自動加載訪問屬性指實體/實體時。爲什麼?它不應該再被訪問?禁用延遲加載仍會加載相關的實體。爲什麼?

My EF version="6.1.3" 

以下線路負荷部門的數據,而我期待它不應該,因爲我已經停用延遲加載,並導航屬性非虛。

Student student = context.Student.select(x => x.Department).First(); 

類:

public class Student 
{ 
    public string Name { get; set;} 
    public string Age { get; set;} 
    public string Date { get; set;} 

    public Department department { get; set } 
} 

public class Department 
{ 
    public string Id { get; set; } 
    public class Name { get; set; } 
    public Student Student { get; set } 
} 

語境

public StudentContext : DbContext 
{ 
    public StudentContext() 
    { 
     this.Configuration.LazyLoadingEnabled = false; 

    } 

} 
+5

您的查詢明確要求部門。當然,它會加載部門數據。 – Amy

+0

所以你想[懶加載](https://msdn.microsoft.com/en-us/library/jj574232(v = vs.113).aspx)?你已經配置了所有配置以便加載(不虛擬,訪問孩子,關閉它)。 –

+0

謝謝,所以我對延遲加載的理解是錯誤的。你的意思是,儘管延遲加載被禁用,但如果我們使用x.blah訪問導航屬性,EF會顯式加載它,並不會抱怨「懶惰加載已禁用,因此我無法加載它。」更好地嘗試「加載加載」或「顯式加載」 ,「 – immirza

回答

1

你有什麼 「懶加載」 方式錯誤的想法。

context.Student.Select(x => x.Department).First(); 

您明確要求Department。英孚將會兌現這一要求。關於您的查詢沒有任何「懶惰」:您是明確要求Department

是的,您通過導航屬性請求Department,但這並不重要,因爲您沒有使用Student的實例。 您直接向數據庫發出查詢。

您現在有一個Department。懶惰加載現在開始發揮作用,因爲您完成了顯式查詢。

該部門有一個小孩財產,Student。由於延遲加載處於禁用狀態,即使數據庫中存在數據,該屬性也將爲空。如果您引用該屬性,則它將爲空,因爲延遲加載被禁用 - EF不會爲您自動獲取數據。您必須明確查詢該屬性。

好的,所以說你明確要求一個Student對象。它的Department屬性將爲空,因爲延遲加載被禁用。引用該屬性不會導致它被加載。您將不得不顯式查詢該屬性。

+0

謝謝,我明白了。 – immirza

1

什麼是延遲加載?

它是由後做單獨的數據庫查詢加載相關數據的能力,你有 執行一些初步的SQL查詢,並加載一些實體。

,首先讓我們來回顧你的類:

  • 教研室不是1:1間與學生的關係。每個部門都可以包含很多學生
  • 學生沒有一個ID屬性
  • 部門也許應該有整數ID
  • 爲了支持延遲加載導航性能應虛擬

考慮到這些,您將獲得以下課程:

public class Student 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Age { get; set; } 
    public string Date { get; set; } 

    public virtual Department Department { get; set; } 
} 

public class Department 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Student> Students { get; set; } 
} 

現在讓我們來看看會發生什麼啓用延遲加載。例如。您正在加載學生:

Student bob = context.Students.FirstOrDefault(s => s.Name == "Bob"); 

,將產生類似

SELECT TOP(1) Name, Age, Date, Department_Id 
FROM Students 
WHERE Name = 'Bob' --actually name will be passed as query parameter 

而且更重要的是,該SQL查詢將被執行,並從服務器響應將被加載到內存中,並映射到Student查詢實體。除了ID已加載外,沒有任何與部門相關的信息現在,如果您嘗試獲取部門詳情

var departmentName = bob.Department?.Name; 

EF將生成用於加載相關部門詳細信息的SQL查詢。類似於

SELECT d.Id, d.Name 
FROM Students s 
INNER JOIN Departments d ON s.Department_Id = d.Id 
WHERE s.Id = 42 -- assume Bob has this id 

並且此查詢將被執行。這是服務器的第二次往返。這就是懶加載的工作原理。

延遲加載被禁用將不會有第二個查詢到服務器。您將只有第一次查詢加載的數據。即部門實體將是null,你將無法獲得它的名字。


現在你的情況 - 你正在通過第一次查詢加載部門數據。其實你的代碼不能編譯,因爲你應該使用Department實體:

Department dep = context.Student.Select(x => x.Department).First(); 

啓用或禁用延遲加載不會影響。因爲正如我剛剛寫的,延遲加載會影響進一步查詢加載相關數據。但不是首先加載初始數據的查詢。在你的情況下,它看起來像

SELECT TOP(1) d.Id, d.Name 
FROM Students s 
LEFT OUTER JOIN Departments d ON s.Department_Id = d.Id 
+1

謝謝,優秀的解釋。 – immirza

+1

@immirza歡迎您。請記住 - 懶加載爲您提供了輕鬆訪問相關實體的好處,就像它們已經從服務器加載一樣,但是您應該小心,因爲每次您要進行新的數據庫往返時 –

相關問題