如果您想在某个任意过滤器上删除许多项目(读取数百或更多),最有效的方法是所谓的“批量删除”。 EFCore.BulkExtensions 允许这样做。检查以下示例:
var toRemoveModels = DataAccess.ModelRepository.All
.Where(m => m.Name.StartsWith("Added model"))
.ToList();
DataAccess.ModelRepository.BulkDelete(toRemoveModels);
在数据库上下文中的实际实现非常简单:
public void BulkDelete<TModel>(IList<TModel> entities) where TModel: class
{
this.BulkDelete(entities, bulkConfig: null);
}
这将生成一堆查询,但仍然比发出大量 DELETE 语句更有效:
SELECT [m].[Id], [m].[MakeId], [m].[Name], [m].[PriceInEur]
FROM [Model] AS [m]
WHERE [m].[Name] LIKE N'Added model' + N'%' AND (LEFT([m].[Name], LEN(N'Added model')) = N'Added model')
go
SELECT columnproperty(object_id('dbo.[Model]'),'Id','IsIdentity');
go
SELECT TOP 0 T.[Id] INTO dbo.[ModelTemp208f3efb] FROM dbo.[Model] AS T LEFT JOIN dbo.[Model] AS Source ON 1 = 0;
go
select @@trancount; SET FMTONLY ON select * from dbo.[ModelTemp208f3efb] SET FMTONLY OFF exec ..sp_tablecollations_100 N'[dbo].[ModelTemp208f3efb]'
go
insert bulk dbo.[ModelTemp208f3efb] ([Id] Int)
go
MERGE dbo.[Model] WITH (HOLDLOCK) AS T USING dbo.[ModelTemp208f3efb] AS S ON T.[Id] = S.[Id] WHEN MATCHED THEN DELETE;
go
DROP TABLE dbo.[ModelTemp208f3efb]
go
注意:执行“批量”删除的更有效方法是提供IQueryable,它指定获取项目的方式并生成类似于以下的DELETE :
DELETE FROM SomeTable
WHERE Id IN (SELECT Id FROM SomeTable WHERE ...)
这更快,因为它不需要加载 EF 实体,也不需要创建临时表和 MERGE 反对它。
我使用了 Entity Framework 6 的库,但找不到 EF Core 的非商业库。