最近主導了旗下某核心項目升級到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了