EF Core 3 的 40 个中断性变更
為了修復(fù) Entify Framework Core 中許多已發(fā)現(xiàn)的缺陷,微軟在 EF Core 3 中引入了 40 個中斷性變更。我們可以在微軟文檔中查看完整的中斷性變更列表,本文僅列舉幾個主要的點。
客戶端查詢
為了突破 EF Core SQL 生成器的限制,默認(rèn)只在客戶端執(zhí)行部分查詢。這意味著對于部分不能轉(zhuǎn)換成 SQL 的 LINQ 查詢,需要從數(shù)據(jù)庫加載數(shù)據(jù)表,并在內(nèi)存中執(zhí)行其余的操作。在 2.1 版本之前,Group By 都是在客戶端執(zhí)行的。
這種方式的缺點是,Where() 子句中的一個問題可能導(dǎo)致 EF Core 加載整張數(shù)據(jù)表。開發(fā)人員還發(fā)現(xiàn),在無法生成相關(guān)子查詢的情況下,它將執(zhí)行成百上千個二級查詢。
新的默認(rèn)行為是 EF Core 僅允許在客戶端執(zhí)行最終的 Select() 操作。如果 EF Core 不能生成正確的 SQL,將引發(fā)異常。開發(fā)人員可以覆蓋這個行為,但微軟更希望開發(fā)者遇到這個問題時先嘗試提交一個 bug 請求。
可以在“3.0 查詢指導(dǎo)原則大綱和決策點“中了解更多有關(guān)該變更的信息。
參數(shù)化及插值 SQL
正如我們在 2017 年報告的那樣,EF Core 的字符串插值特性引起了許多關(guān)注。使用該特性可以將內(nèi)插字符串自動轉(zhuǎn)換為參數(shù)化 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 是正確參數(shù)化的,而 v2 則引入了一個 SQL 注入漏洞。
為了消除上述漏洞,將移除 FromSql 函數(shù),并使用 FromSqlRawand 和 FromSqlInterpolated 替代。
臨時鍵
EF Core 通常會創(chuàng)建臨時主鍵來跟蹤新實體。這些臨時主鍵以負(fù)數(shù)的形式存儲在鍵屬性中(例如 CustomerKey 或 OrderId)。理論上,這些臨時主鍵在生成時會被真正的鍵所替換,不過也存在幾個例外情況,比如那些在用戶界面上顯示的假鍵甚至?xí)槐4娴綌?shù)據(jù)庫中。
EF Core 3 將把此類跟蹤信息轉(zhuǎn)移到實體的跟蹤信息中,讓鍵屬性只持有數(shù)據(jù)。
級聯(lián)刪除時機
在調(diào)用諸如 context.Remove() 等方法時,級聯(lián)刪除將立即發(fā)生。在此之前,EF Core 在 SaveChanges 被調(diào)用之前不會計算哪些子項被刪除,因此很難預(yù)測到底會發(fā)生什么。該變更主要影響那些用于記錄將要修改 / 刪除哪些數(shù)據(jù)項日志的代碼。
可以通過將 CascadeDeleteTiming 和 DeleteOrphansTiming 選項設(shè)置成 CascadeTiming.OnSaveChanges 來還原以前的行為。
查詢類型已過時
與之前版本的 Entity Framework 不同,EF Core 被設(shè)計成只能處理包含主鍵的數(shù)據(jù)表。這是有問題的,因為視圖或存儲過程的結(jié)果沒有主鍵。所以 EF core 2.1 引入了查詢類型的概念。
本質(zhì)上,查詢類型使用的是并行對象模型。開發(fā)人員使用 DbQuery?而不是 DbSet?來定義它們,使用 ModelBuilder.Query<>() 而不是 ModelBuilder.Entity<>() 來注冊它們,并使用 DbContext.Query<>() 而不是 DbContext.Set<>() 來調(diào)用它們。
許多開發(fā)人員抱怨查詢類型和實體類型之間存在不必要的混淆,因此查詢類型被移除了。從 EF Core 3 開始,開發(fā)人員應(yīng)該對所有數(shù)據(jù)源使用常規(guī)的 DbSet 模型。如果沒有主鍵,開發(fā)人員在注冊實體時只需使用 .HasNoKey() 來注解它們。
忽略屬性的 Getter 和 Setter
在過去,除非要物化查詢結(jié)果,否則 EF Core 將調(diào)用屬性的 getter 或 setter 方法。在進行查詢時,如果已知屬性的支持字段,它將繞過屬性,直接寫入底層字段。
在這個變更之后,如果已知屬性的支持字段,將始終使用底層支持字段。這樣做的好處是可以防止意外觸發(fā)業(yè)務(wù)邏輯。
缺點是諸如更新計算字段之類的業(yè)務(wù)邏輯也不會被觸發(fā)。因此,我們可能需要修改 UsePropertyAccessMode 來獲得我們想要的行為。
支持字端檢測
在檢測支持字段時,代碼有時候會有歧義。在過去,EF Core 只能根據(jù)內(nèi)部排名系統(tǒng)來猜測應(yīng)該設(shè)置哪個字段。
在 EF Core 3 中,任何有歧義的地方都將拋出異常。不過,開發(fā)人員必須手動指出要使用模型生成器生成的哪個字段。
用 ValueTask 替換 Task
將 Task 作為對象被認(rèn)為是.NET 的最大錯誤之一。雖然對于長時間運行的任務(wù)來說是可以接受的,但當(dāng)創(chuàng)建了大量的短期任務(wù)時,它常常會造成過大的內(nèi)存壓力,所以新版本引入了基于結(jié)構(gòu)的備選方案 ValueTask 。
為了支持這種新類型,更新了 FindAsync 和 NextValueAsync 等幾個方法,讓它們返回 ValueTask 而不是 Task 。這不會影響那些等待獲取結(jié)果的代碼,但如果要對任務(wù)執(zhí)行其他操作,可能需要調(diào)用 AsTask() ,將其從 ValueTask 轉(zhuǎn)換到 Task 。
簡化 IEntityType 和 IProperty
刪除了這兩個接口中的五個屬性,并用擴展方法進行替換。這樣做的依據(jù)是如果接口表面越小就容易實現(xiàn)。
原文地址:https://www.infoq.cn/article/jWDSt47Xu-FRdIEoRIuM
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?
總結(jié)
以上是生活随笔為你收集整理的EF Core 3 的 40 个中断性变更的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NET项目迁移到.NET Core操作
- 下一篇: 联手微软,Docker公司将推出Dock