簡體   English   中英

使用 AsNoTracking() 延遲加載實體框架

[英]Entity Framework lazy loading with AsNoTracking()

我們目前正在為實體框架使用延遲加載並遇到out of memory exception 我們遇到這個異常的原因是因為 Linq 查詢加載了大量數據,並且在后期階段它使用延遲加載來加載導航屬性。 但是因為我們不使用NoTrackingChanges實體框架緩存構建得非常快,這會導致內存不足錯誤。

我對 EF 的理解是,除非您想更新查詢中返回的對象,否則我們應該始終在查詢中使用NoTrackingChanges

然后我使用NoChangeTracking進行了測試:

var account = _dbcontext.Account
                        .AsNoTracking()
                        .SingleOrDefault(m => m.id == 1); 
var contactName = account.Contact.Name

但我收到以下錯誤:

System.InvalidOperationException:當返回帶有 NoTracking 合並選項的對象時,僅當 EntityCollection 或 EntityReference 不包含對象時才能調用 Load。

您已指定 EF 不跟蹤您的實例化Account值:

var account = _dbcontext.Account.AsNoTracking().SingleOrDefault(m=>m.id == 1);

因此,嘗試訪問導航屬性將永遠不會奏效:

var contactName = account.Contact.Name

您可以使用Include()顯式包含所需的導航屬性。 所以以下應該工作:

var account = _dbcontext.Account
  .Include(a => a.Contact)
  .AsNoTracking()
  .SingleOrDefault(m=>m.id == 1);

var contactName = account.Contact.Name;  // no exception, it's already loaded

我真的不相信使用 AsNoTracking 可以防止使用延遲加載

它可以非常快速地進行測試:

DotNetFiddle 完整示例

public static void Main()
{
    var actor1 = new Actor { Id = 1, Name = "Vin Diesel" }; 
    var movie1 = new Movie { Id = 1, Title = "Fast and Furious", PrimaryActor = actor1 };
    using (var context = new MovieDb())
    {

        Console.WriteLine("========= Start Add: movie1 ==============");
        context.Movies.Add(movie1);
        context.SaveChanges();
        Console.WriteLine("========= END Add: movie1 ==============");

        var m1 = context.Movies.First();
        Console.WriteLine(m1.PrimaryActor.Name);

        var m2 = context.Movies.Include(m => m.PrimaryActor).AsNoTracking().First();
        Console.WriteLine(m2.PrimaryActor.Name);

        var m3 = context.Movies.AsNoTracking().First();
        Console.WriteLine(m3.PrimaryActor.Name);
    }
}

輸出:

======== 開始添加:movie1 ==============
========== 結束添加:movie1 ============
范·迪塞爾
范·迪塞爾
運行時異常(第 31 行):未將對象引用設置為對象的實例。

變量m1由上下文跟蹤,因此它可以延遲加載導航屬性並打印值。 m2沒有被跟蹤,但我已經明確地包含了導航屬性,所以它會打印值。 m3沒有被跟蹤,我沒有明確包含它,因此該值為null ,我們得到了一個 NRE。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM