最近主导了旗下某核心项目升级到EfCore3git
因为以前Core2升级时候也踩过很多的坑不少东西都有规划和准备,总体上仍是没出太大问题github
可是最近忽然发现efcore对于使用了ownedType的生成语句有问题并发
查找了一下资料发现已经有人在efcore的github上开了issus了,而且还讨论的蛮多的了性能
https://github.com/dotnet/efcore/issues/18299 测试
EfCore自2.0的时候引入了一个叫OwnedType的特性,是用于完善以前EfCore1.x相比于Ef6使其少了的ComplexType特性ui
正常来讲咱们用Ef的时候是一个类映射到一个表,可是有时候某些表字段过多的状况下,咱们可能会想整理下把一个表里某些信息放到一个子类里,可是其余信息仍是在主类blog
形如get
class Order { public int Id { get; set; } public string Title { get; set; } public Address Address { get; set; } } class Address { public string Street { get; set; } public string City { get; set; } }
而后DbContext里配置下
modelBuilder.Entity<Order>().OwnsOne(x => x.Address);
这种状况下最理想生成的语句应该是相似
select Id,Title,Street,City from Orders
这个样子的形式才对,而后EfCore内部再经过本身映射的形式把后面4个字段映射到Author类里的Address这个类里
可是在EfCore3里他生成的语句是形如
SELECT o."Id", o."Title", t."Id", t."Address_City", t."Address_Street" FROM "Orders" AS o LEFT JOIN ( SELECT o0."Id", o0."Address_City", o0."Address_Street", o1."Id" AS "Id0" FROM "Orders" AS o0 INNER JOIN "Orders" AS o1 ON o0."Id" = o1."Id" WHERE (o0."Address_Street" IS NOT NULL) OR (o0."Address_City" IS NOT NULL) ) AS t ON o."Id" = t."Id" WHERE (t."Id" IS NULL)
尽管严格来讲这个并不影响逻辑,可是这样子join的话对Sql的性能和效率有挺很差的负面影响string
就那个issus里也有人作了测试,结果下图it
纵坐标是每秒执行的查询数(简单理解为并发数吧)
横坐标是表里有多少数据
能够看到表的数据量上升以后使用了OwnedType的EfCore3会出现显著下滑(本身join本身多了)
另外该问题在EfCore2的时候是没有的,就Core3才有(直觉是Core3的OwnedType被魔改了能够支持OwnsMany等的支持的时候引入的)
接下来就是一个好消息和一个坏消息了
好消息是EfCore那边承认了这个问题而后当前EfCore 5 preview-3修复了这个问题
坏消息是至少目前确认这个修复不会合并到EfCore3.1.x(后期会不会有变数不清楚)
感受这个蛮坑的,通常公司用的话都会是优先选用LTS,而当前的LTS就是3.1
而接下来的NetCore5(含EfCore5)并非LTS因此对于公司组织的线上采用率应该会相对较低
那难道修复这个问题还要等一个目前还没规划的NetCore5.1?那是否是要等的有点儿过久了
最后,若是有升级EfCore3的且用了OwnedType(至关于Ef6时期的ComplexType)请谨慎评估下这个问题对你可能形成的影响
毕竟目前看起来,降级回去不大可能,烧香保佑下fix path能到3.1.x要么就只能期望Core5.1了