2013-05-03 28 views
5

我首先使用EF Model與POCO實體和自定義DbContexts。我的問題是,設置LazyLoadingEnabled=false不會影響任何東西,導航屬性仍然​​加載。 下面是我簡化的例子。LazyLoadingEnabled設置似乎不適用於EF 5

實體程序。程序可以是其它程序的一部分:

namespace Domain.Entities 
{ 
    using System; 
    using System.Collections.Generic; 

    public partial class Program 
    { 
     public Program() 
     { 
      this.Programs = new HashSet<Program>(); 
     } 

     public int Id { get; set; } 
     public string Title { get; set; } 
     public string Description { get; set; } 
     public System.DateTime StartDate { get; set; } 
     public System.DateTime EndDate { get; set; } 
     public Nullable<int> ProgramId { get; set; } 

     public virtual ICollection<Program> Programs { get; set; } 
     public virtual Program OwnerProgram { get; set; } 
    } 
} 

的的DbContext:

namespace Infrastructure.Model 
{ 
    public class ProgramContext : DbContext 
    { 
     public ProgramContext() 
      : base("name=MyContainer") 
     { 
      Configuration.LazyLoadingEnabled = false; 
     } 

     public DbSet<Program> Programs { get; set; } 
    } 
} 

這是我如何使用它:

private ProgramContext _dbContext = new ProgramContext(); 

// GET api/program 
public IEnumerable<Program> GetPrograms() 
{ 
    List<Program> list = _dbContext.Programs.ToList(); 
    return list; 
} 

使用上述樣品,EF仍然加載程序和Program類的OwnerProgram屬性。我嘗試刪除虛擬關鍵字,禁用代理創建,並驗證模型本身的LazyLoadingEnabled=false

我錯過了什麼嗎?

回答

6

您所看到的效果叫做關係修正

其實導航屬性是而不是顯式加載。查詢_dbContext.Programs.ToList()僅從數據庫加載整個Programs表。這只是一個簡單的SQL查詢(如SELECT * FROM ProgramsTable),沒有任何WHERE子句,也沒有任何JOIN到相關的行。

還沒有懶加載發生在這裏(它真的不能,如果你禁用它,如果你禁用甚至動態代理),當您訪問program.Programsprogram.OwnerProgram導航性能。

由於查詢(加載所有程序)將加載導航屬性可引用的所有程序,導致您的查詢結果實現時導航屬性會填充。 EF檢測到這些相關實體已經在內存中並自動將其放入導航屬性中。

您可以驗證這一點,如果你不加載所有方案,但只,例如,一個單一的一個:現在

Program program = _dbContext.Programs.FirstOrDefault(); 

program.Programsprogram.OwnerProgramnull - 除非加載program是部分它自己的program.OwnerProgram集合或是自己的OwnerProgram

+1

謝謝,這就是我所看到的。有沒有什麼辦法可以讓EF不加載導航屬性,除非我使用.Include()? – gixen 2013-05-04 20:05:11

+0

@gixen:如上所述,它並不真正「加載」。關係修正只是將實體放入已經加載的導航集合和引用中。所以,沒有查詢開銷。如果要在加載後修改實體,則需要更改跟蹤,並且不能禁用此行爲。如果沒有在只讀情況下進行更改跟蹤,您可以嘗試'_dbContext.Programs.AsNoTracking()。ToList()'。但我不確定在這種情況下它是否會有所幫助。 – Slauma 2013-05-04 20:52:01

+0

我從這個答案中得出的結論是沒有辦法在沒有打開上下文的情況下在EF中加載整個對象圖形以延遲加載導航屬性。 OR .Include(「NavigationProtperyName」)可以顯式調用來加載導航屬性,但它是每個查詢所必需的。 – 2013-11-01 16:49:32

2

「EF仍然加載程序 類的程序和OwnerProgram屬性」

這是正確的行爲,但不是延遲加載的導航性能,它急切地加載它們。

這意味着當檢索到Program實體並填充導航屬性時,將立即執行檢索導航屬性值所需的數據庫查詢。

LazyLoadingEnabled設置爲true時,只有在嘗試訪問導航屬性時,纔會觸發這些查詢。這也適用於當您將鼠標懸停在導航屬性上並且附加了調試器時,這可能會導致您認爲實體未被延遲加載 - 實際上它們是 - 調試器正在訪問導航屬性,所以實體框架加載它。

您可以運行SQL分析器,例如this one以準確查看在您調試代碼時何時觸發查詢。

0

對於上面的示例,EF仍加載Program類的Programs和OwnerProgram 屬性。我嘗試刪除虛擬 關鍵字,禁用代理創建,並驗證模型本身的 LazyLoadingEnabled = false。

我錯過了什麼嗎?

您需要刪除初始化這些屬性的默認構造函數。

相關問題