繁体   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