我做了一个小测试,启用了懒惰的Model.Item2
(使用EF Core 2.1.4)
我遍历有无仪器,这就是我得到的结果
案例1
loading.optionsBuilder.UseLazyLoadingProxies().UseSqlServer(ConnectionString);
案例2
var instruments = db.instruments.OrderBy(t=>t.id).Include(t=>t.NavPro1).ThenInclude(t=>t.NavPro2).Take(200);
然后
var instruments = db.instruments.OrderBy(t=>t.id).Include(t=>t.NavPro1).ThenInclude(t=>t.NavPro2).Take(200);
花7s即可获得10万行,而不会延迟加载
需要160 s才能获得3k行的延迟加载。
如何获得良好的性能?
答案 0 :(得分:3)
是,请避免延迟加载。期间。
问题是-总是追溯到曾经构建的每个ORM-如果您进行延迟加载,则每个引用都是延迟加载。往返1次以上(每个住宿至少一次)。分开的SQL执行,分开的网络时间。这加起来非常快。
这就是为什么以前编写的每个ORM通过.include语句在EF变体中都支持NON延迟加载的原因,该语句扩展了SQL或生成了单独的SQL(ef核心,列出以实现与有效sql的关系)。
如果您坚持使用延迟加载-就像您的问题所暗示的那样,您不会在代码上散布任何魔法尘,从而避免了延迟加载的隐含负面影响。
现在,补充一点-3.0之前的任何EF Core都已损坏。是的,那是3.0-甚至是2.2。看到,各个部分都有很多问题,包括基本的LINQ。和性能。至少2.2(希望在一个月内出现)应该可以解决一些问题。在此之前,请尝试使用.include和AsNoTracking-因为IIRC存在一个性能错误,在加载20万行时也会遇到问题。
答案 1 :(得分:2)
这是一个普遍的问题,称为N + 1问题。
这里发生的是,当您使用延迟加载时,您会有更多的请求。
在使用Include
的情况下,您有一个巨大的请求可以提供所有数据-或每个表一个请求,因此您的情况下为三个请求。这取决于您的数据的确切结构。
在延迟加载的情况下,您对仪器有一个请求,而对于每种仪器,则有另一个对NavPro1的请求。对于每个NavPro1
元素,您还需要另一个NavPro2。
因此,如果您有1000台仪器,每台仪器有10台NavPro1,则现在您有1 +(1000 *(1 + 10))= 11001个请求,而不是最多三个请求。那太慢了,期间。
答案 2 :(得分:-1)
https://github.com/aspnet/EntityFrameworkCore/issues/12451
这是解决方案
服务 .AddDbContext(b => b.ReplaceService());