星期四, 4月 04, 2024

[EFCore] ExecuteUpdate 和 ExecuteDelete

ExecuteUpdate 和 ExecuteDelete 為 EFCore 7 推出功能,可以直接對單一 Table 進行 update 和 delete,不牽涉到 Entity Tracking,且該語法會直接執行,不需要使用 SaveChange(),但SaveChange() 自帶交易,而 ExecuteDelete 和 ExecuteUpdate 沒有,要自行開啟 Transaction 來確保一致性喔

ExecuteDelete

master-detail table 架構 EX:訂單,要使用 ORM 刪除的話,語法會如同下列
internal class Program
{
    static void Main(string[] args)
    {
        using var dbContext = new AdventureWorks2022Context();

        var header = dbContext.SalesOrderHeaders.Single(w => w.SalesOrderId == 43659);
        var detail = dbContext.SalesOrderDetails.Where(w => w.SalesOrderId == 43659).ToList();

        dbContext.SalesOrderDetails.RemoveRange(detail);
        dbContext.SalesOrderHeaders.Remove(header);

        dbContext.SaveChanges();
    }
}
使用 SQL Profile 側錄語法可以看見是先把資料抓出來後,根據 SalesOrderDetail Table PK 一筆一筆資料進行刪除

下列為 SalesOrderDetails 刪除語法,留三個 delete 來示意
exec sp_executesql N'SET NOCOUNT ON;
DELETE FROM [Sales].[SalesOrderDetail]
WHERE [SalesOrderDetailID] = @p0 AND [SalesOrderID] = @p1;
SELECT @@ROWCOUNT;

DELETE FROM [Sales].[SalesOrderDetail]
WHERE [SalesOrderDetailID] = @p2 AND [SalesOrderID] = @p3;
SELECT @@ROWCOUNT;

DELETE FROM [Sales].[SalesOrderDetail]
WHERE [SalesOrderDetailID] = @p4 AND [SalesOrderID] = @p5;
SELECT @@ROWCOUNT;

',N'@p0 int,@p1 int,@p2 int,@p3 int,@p4 int,@p5 int,@p0=15,@p1=43661,@p2=16,@p3=43661,@p4=17,@p5=43661'

以往為了提高效能就乾脆直接下 TSQL 根據訂單編號去刪除,現在有 ExecuteDelete 後就可以直接來進行刪除
internal class Program
{
    static void Main(string[] args)
    {
        using var dbContext = new AdventureWorks2022Context();
        using var tran = dbContext.Database.BeginTransaction();
        
        dbContext.SalesOrderDetails
            .Where(w => w.SalesOrderId == 123)
            .ExecuteDelete();
        
        dbContext.SalesOrderHeaders
            .Where(w => w.SalesOrderId == 123)
            .ExecuteDelete();
        
        tran.Commit();
    }
}

ExecuteUpdate

ExecuteUpdate 可以透過 SetProperty 來針對多個欄位進行資料更新,用個範例紀錄
internal class Program
{
    static void Main(string[] args)
    {
         using var dbContext = new AdventureWorks2022Context();
         
         int numUpdated = dbContext.SalesOrderDetails
                .Where(w => w.SalesOrderId == 43664)
                .ExecuteUpdate(e =>
                e.SetProperty(sod => sod.ModifiedDate, DateTime.Now));
         
         Console.WriteLine("影響筆數 : " + numUpdated);
    }
}

沒有留言:

張貼留言