EF 高效批量更新

介绍

在处理大量数据时,Entity Framework 的默认更新机制可能会导致性能问题。每次调用 SaveChanges 方法时,EF 都会将更改发送到数据库,这对于单个或少量实体的更新是高效的,但对于大量数据的更新或删除操作,可能会变得低效。本文将介绍 Entity Framework 7 引入的两种新方法——ExecuteDeleteExecuteUpdate,它们可以显著提高批量更新的性能。

Entity Framework 的默认行为

Entity Framework 旨在为大多数用例提供高效的变更跟踪。它只发送已更改属性或关系的更新,并智能地批量处理更新以减少数据库往返。所有更改都会无缝同步到 DB 上下文和数据库中。

但如果你需要执行大量更新或删除操作呢?你需要从数据库中加载所有实体,更改它们,然后保存更改。对于大量数据,这可能会产生性能问题。

新批量更新方法

ExecuteDelete

ExecuteDelete 方法允许你直接在数据库中删除实体,而无需将它们加载到内存中。这可以显著提高性能,尤其是当需要删除大量记录时。

以下是一个使用 ExecuteDelete 的示例:

    .Where(p => p.StockQuantity == 0)
    .ExecuteDeleteAsync();

这条代码将生成以下 SQL:

DELETE FROM[p]
    FROM [Products] AS[p]
    WHERE[p].[StockQuantity] = 0

ExecuteUpdate

ExecuteUpdate 方法允许你直接在数据库中更新实体,而无需将它们加载到内存中。这可以显著提高性能,尤其是当需要更新大量记录时。
以下是一个使用 ExecuteUpdate 的示例:

.Where(p=>p.Category=="iPhone").ExecuteUpdateAsync(p=>p.SetProperty(x=>x.StockQuantity,0));

这条代码将生成以下 SQL:

UPDATE[p]
    SET[p].[StockQuantity] = 0
    FROM[Products] AS[p]
    WHERE[p].[Category] = N'iPhone'

使用场景与性能优势

ExecuteDelete 和 ExecuteUpdate 方法特别适合以下场景:

  • 需要对大量记录进行更新或删除操作。
  • 不需要将实体加载到内存中,从而节省内存和减少数据库往返。
  • 需要快速执行更新操作,而不必等待 SaveChanges 方法的调用。
    这些方法可以显著提高性能,尤其是在处理大量数据时。

限制与注意事项

限制与注意事项
尽管 ExecuteDelete 和 ExecuteUpdate 的使用非常简单,但需要注意它们的限制:

  • 这些方法的多次调用不能批量处理。每次调用都会向数据库发送一个单独的操作。
  • Entity Framework 不会为这些方法创建隐式事务,就像 SaveChanges 方法那样。因此,如果你有多个批量更新操作,并且希望在一个事务中执行它们,你需要显式地开始一个事务。
  • 执行 ExecuteDelete 或 ExecuteUpdate 后,Entity Framework 不会同步更改。因此,不建议将它们与 SaveChanges 调用混合使用。
  • SaveChanges 提供并发控制。由于 ExecuteDelete 和 ExecuteUpdate 不涉及变更跟踪器,因此它们不支持并发控制。但它们会返回受影响的行数。
  • 这些方法只针对一个表。你不能删除或更新关系。因此,如果你想从两个相关表中删除记录,你需要先删除依赖项,然后再删除主项。
  • 只有关系型数据库提供程序支持这些方法。

拥有类型的支持

在 Entity Framework 8 中,ExecuteUpdate 和 ExecuteDelete 方法得到了增强,现在可以支持拥有类型(Owned Types)。
以下是一个示例,展示如何在拥有类型上使用 ExecuteUpdate:

publiclongIdget;set;publicstringNameget;set;publicPriceInfoPriceInfoget;set;publicstringCategoryget;set;publicintStockQuantityget;set;publicclassPriceInfopublicdecimalPriceget;set;publicstringCurrencyget;set;

配置实体:

modelBuilder.Entity<Product>().OwnsOne(p=>p.PriceInfo);

以下是一个使用 ExecuteUpdate 更新拥有类型的示例:

.Where(p=>p.Category=="iPhone15").ExecuteUpdateAsync(p=>p.SetProperty(x=>x.PriceInfo.Price,799).SetProperty(x=>x.StockQuantity,1000));

生成的 SQL 如下:

UPDATE Products AS p
    SET p.PriceInfo_Price = 799.0
    SELECT 1
    FROM Products AS p
    WHERE p.Category == N'iPhone 15'

总结

Entity Framework 7 引入的 ExecuteDelete 和 ExecuteUpdate 方法可以显著提高批量更新操作的性能。然而,了解它们的限制对于高效使用它们至关重要。通过合理使用这些方法,你可以显著提升应用程序在处理大量数据时的性能。

posted @ 2025-02-28 09:28  初久的私房菜  阅读(391)  评论(0)    收藏  举报
作者:初久的私房菜
好好学习,天天向上
返回顶部小火箭
好友榜:
如果愿意,把你的博客地址放这里
张弛:https://blog.zhangchi.fun/