EF Core 3 的 40 箇中斷性變更

爲了修復Entify Framework Core中許多已發現的缺陷,微軟在EF Core 3中引入了40箇中斷性變更。我們可以在微軟文檔中查看完整的中斷性變更列表,本文僅列舉幾個主要的點。

客戶端查詢

爲了突破EF Core SQL生成器的限制,默認只在客戶端執行部分查詢。這意味着對於部分不能轉換成SQL的LINQ查詢,需要從數據庫加載數據表,並在內存中執行其餘的操作。在2.1版本之前,Group By都是在客戶端執行的。

這種方式的缺點是,Where() 子句中的一個問題可能導致EF Core加載整張數據表。開發人員還發現,在無法生成相關子查詢的情況下,它將執行成百上千個二級查詢。

新的默認行爲是EF Core僅允許在客戶端執行最終的 Select() 操作。如果EF Core不能生成正確的SQL,將引發異常。開發人員可以覆蓋這個行爲,但微軟更希望開發者遇到這個問題時先嚐試提交一個bug請求。

可以在“3.0查詢指導原則大綱和決策點“中瞭解更多有關該變更的信息。

參數化及插值SQL

正如我們在2017年報告的那樣,EF Core的字符串插值特性引起了許多關注。使用該特性可以將內插字符串自動轉換爲參數化SQL,但前提是這些字符串之前沒有被存儲在臨時變量中。

v1 = context.Customers.FromSql($"SELECT * FROM Customers WHERE City = {city}");


var sql = $"SELECT * FROM Customers WHERE City = {city}";
v2 = context.Customers.FromSql(sql);

在上面的例子中,v1是正確參數化的,而v2則引入了一個SQL注入漏洞。

爲了消除上述漏洞,將移除 FromSql 函數,並使用FromSqlRawand 和 FromSqlInterpolated 替代。

臨時鍵

EF Core通常會創建臨時主鍵來跟蹤新實體。這些臨時主鍵以負數的形式存儲在鍵屬性中(例如CustomerKey或OrderId)。理論上,這些臨時主鍵在生成時會被真正的鍵所替換,不過也存在幾個例外情況,比如那些在用戶界面上顯示的假鍵甚至會被保存到數據庫中。

EF Core 3將把此類跟蹤信息轉移到實體的跟蹤信息中,讓鍵屬性只持有數據。

級聯刪除時機

在調用諸如 context.Remove() 等方法時,級聯刪除將立即發生。在此之前,EF Core在 SaveChanges 被調用之前不會計算哪些子項被刪除,因此很難預測到底會發生什麼。該變更主要影響那些用於記錄將要修改/刪除哪些數據項日誌的代碼。

可以通過將 CascadeDeleteTiming 和 DeleteOrphansTiming 選項設置成CascadeTiming.OnSaveChanges 來還原以前的行爲。

查詢類型已過時

與之前版本的Entity Framework不同,EF Core被設計成只能處理包含主鍵的數據表。這是有問題的,因爲視圖或存儲過程的結果沒有主鍵。所以EF core 2.1引入了查詢類型的概念。

本質上,查詢類型使用的是並行對象模型。開發人員使用 DbQuery 而不是 DbSet 來定義它們,使用 ModelBuilder.Query<>() 而不是 ModelBuilder.Entity<>() 來註冊它們,並使用DbContext.Query<>() 而不是 DbContext.Set<>() 來調用它們。

許多開發人員抱怨查詢類型和實體類型之間存在不必要的混淆,因此查詢類型被移除了。從EF Core 3開始,開發人員應該對所有數據源使用常規的DbSet模型。如果沒有主鍵,開發人員在註冊實體時只需使用 .HasNoKey() 來註解它們。

忽略屬性的Getter和Setter

在過去,除非要物化查詢結果,否則EF Core將調用屬性的getter或setter方法。在進行查詢時,如果已知屬性的支持字段,它將繞過屬性,直接寫入底層字段。

在這個變更之後,如果已知屬性的支持字段,將始終使用底層支持字段。這樣做的好處是可以防止意外觸發業務邏輯。

缺點是諸如更新計算字段之類的業務邏輯也不會被觸發。因此,我們可能需要修改UsePropertyAccessMode 來獲得我們想要的行爲。

支持字端檢測

在檢測支持字段時,代碼有時候會有歧義。在過去,EF Core只能根據內部排名系統來猜測應該設置哪個字段。

在EF Core 3中,任何有歧義的地方都將拋出異常。不過,開發人員必須手動指出要使用模型生成器生成的哪個字段。

用ValueTask 替換 Task

將Task作爲對象被認爲是.NET的最大錯誤之一。雖然對於長時間運行的任務來說是可以接受的,但當創建了大量的短期任務時,它常常會造成過大的內存壓力,所以新版本引入了基於結構的備選方案 ValueTask 。

爲了支持這種新類型,更新了 FindAsync 和 NextValueAsync 等幾個方法,讓它們返回 ValueTask 而不是 Task 。這不會影響那些等待獲取結果的代碼,但如果要對任務執行其他操作,可能需要調用 AsTask() ,將其從 ValueTask 轉換到 Task 。

簡化IEntityType 和IProperty

刪除了這兩個接口中的五個屬性,並用擴展方法進行替換。這樣做的依據是如果接口表面越小就容易實現。

查看英文原文:40 Breaking Changes in EF Core 3

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章