Zack。EFCore。Batch是一個支援在EF Core中高效刪除和更新資料的開源庫。我們知道,EF Core中不支援高效的刪除和更新資料,所有的更新和操作都是逐條資料處理。比如,如果使用如下的語句刪除實現“刪除所有價格大於10元的書“:
ctx。RemoveRange(ctx。Books。Where(b => b。Price > 33))
那麼,EF Core會先執行Select * from books where price>33,然後再對於每一條資料執行delete from books where id=@id進行刪除。EF Core中批次資料的更新原理也是類似。因此在EF Core中進行大量資料的批次刪除、更新效率是比較低的。
為了能夠實現 “一句SQL實現資料的刪除、更新“,我開發了開源專案Zack。EFCore。Batch,這個開源專案實現瞭如下批次刪除的寫法:
await ctx。DeleteRangeAsync
上面的C#程式碼就會執行如下的SQL語句,從而實現“一句SQL刪除資料“的效果:
Delete FROM [T_Books] WHERE ([Price] > @__p_0) OR ([AuthorName] = @__s_1)
這個開源專案使用EF Core實現SQL語句的翻譯,因此只要EF Core支援的資料庫,對應的Linq操作都可以實現翻譯成對應的方言SQL,比如下面的批次更新操作的Linq程式碼:
await ctx。BatchUpdate
在SQL Server資料庫下就會翻譯成一條Update語句,如下:
Update [T_Books] SET [Price] = [Price] + 3。0E0, [Title] = @__s_1, [AuthorName] = COALESCE(SUBSTRING([Title], 3 + 1, 2), N‘’) + COALESCE(UPPER([AuthorName]), N‘’), [PubTime] = GETDATE()WHERE ([Id] > @__p_0) OR ([AuthorName] IS NOT NULL AND ([AuthorName] LIKE N‘Zack%’))
經歷使用者幾個月的使用和反饋issue,目前專案已經升級到1。4。3版,支援SQLServer、MySQL、PostgreSQL、Oracle、SQLite資料庫。理論上來講,只要EF Core支援的資料庫,Zack。EFCore。Batch都可以支援。如果您有其他資料庫需要支援,請和我聯絡。
除了已有的特性之外,Zack。EFCore。Batch新版增加了如下特性。
特性一、基於實體關係的資料過濾
在過濾條件中支援實體之間的關係。例如:
ctx。 DeleteRangeAsync
特性二、支援資料的批次插入
可以用如下的方式進行高效的批次插入:
List
BulkInsert()底層使用各個資料庫的BulkCopy機制實現資料插入,因此插入效率非常高。目前有如下兩個缺點:不支援關聯資料的自動插入,對於關聯的物件,請同樣呼叫BulkInsert()進行插入;由於PostgreSQL的。NET Core Provider還沒有支援BulkCopy,所以目前Zack。EFCore。Batch暫不支援PostgreSQL,我後面再去想辦法解決。
特徵三、支援Take()、Skip()來限制刪除和更新資料的範圍
批次刪除和批次更新都支援透過Take()、Skip()來實現部分刪除和部分更新,例子程式碼如下:
await ctx。Comments。Where(c => c。Article。Id == id)。Skip(3)。DeleteRangeAsync
具體用法請訪問開源專案地址:https://github。com/yangzhongke/Zack。EFCore。Batch
NuGet地址:https://www。nuget。org/packages/Zack。EFCore。Batch/