介绍
在处理大量数据时,Entity Framework 的默认更新机制可能会导致性能问题。每次调用 SaveChanges
方法时,EF 都会将更改发送到数据库,这对于单个或少量实体的更新是高效的,但对于大量数据的更新或删除操作,可能会变得低效。本文将介绍 Entity Framework 7 引入的两种新方法——ExecuteDelete
和 ExecuteUpdate
,它们可以显著提高批量更新的性能。
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] = 0FROM[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 pSET p.PriceInfo_Price = 799.0SELECT 1FROM Products AS pWHERE p.Category == N'iPhone 15'
总结
Entity Framework 7 引入的 ExecuteDelete 和 ExecuteUpdate 方法可以显著提高批量更新操作的性能。然而,了解它们的限制对于高效使用它们至关重要。通过合理使用这些方法,你可以显著提升应用程序在处理大量数据时的性能。