本文介绍了使用AsNoTracking()的实体框架延迟加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们目前正在对Entity Framework使用延迟加载,并遇到out of memory exception.之所以会遇到此异常,是因为Linq查询会加载大量数据,而在后期则使用延迟加载来加载导航属性.但是因为我们不使用NoTrackingChanges,所以Entity Framework缓存会很快建立,这会导致内存不足错误.

We are currently using lazy loading for Entity Framework and running into out of memory exception. The reason why we're running into this exception is because the Linq query loads a lot of data and at latter stages it's using lazy loading to load navigation properties. But because we don't use NoTrackingChanges Entity Framework cache builds up really quickly which results in out of memory error.

我对EF的理解是,除非您要从查询中更新返回的对象,否则我们应该始终在查询上使用NoTrackingChanges.

My understanding with EF is the we should always use NoTrackingChanges on query unless you want to update the returned object from the query.

然后我使用NoChangeTracking进行了测试:

I then tested using NoChangeTracking:

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

但出现以下错误:

推荐答案

您已指定EF不跟踪实例化的Account值:

You've specified for EF to not track your instantiated Account value:

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

因此尝试从中访问导航属性将永远无法进行:

Thus trying to access navigation properties off of them will never work:

var contactName = account.Contact.Name

您可以使用Include()明确包含所需的导航属性.因此,以下方法应该起作用:

You can explicitly include navigation properties you want by using the Include(). So the following should work:

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

可以非常快速地对其进行测试:

It can be tested really quickly:

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);
    }
}

输出:

上下文跟踪变量m1,因此可以延迟加载导航属性并打印该值. m2不会被跟踪,但是我已经明确包含了navigation属性,因此它会打印值. m3没有被跟踪,我也没有明确地包含它,因此该值是null,我们得到一个NRE.

The variable m1 is tracked by the context, thus it can Lazy Load the navigation property and prints the value. m2 is not tracked, but I've explicitly included the navigation property so it prints the value. m3 is not tracked and I have not included it explicitly thus the value is null and we get a NRE.

这篇关于使用AsNoTracking()的实体框架延迟加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-16 04:00