If you want to remove many items (read hundreds or more) on some arbitrary filter, the most efficient way would be a so called "bulk delete". EFCore.BulkExtensions allows that. Check an example below:
var toRemoveModels = DataAccess.ModelRepository.All
.Where(m => m.Name.StartsWith("Added model"))
.ToList();
DataAccess.ModelRepository.BulkDelete(toRemoveModels);
where the actual implementation within the database context is as simple as:
public void BulkDelete<TModel>(IList<TModel> entities) where TModel: class
{
this.BulkDelete(entities, bulkConfig: null);
}
This will generate a bunch of queries, but will still be more efficient than issuing lots of DELETE
statements:
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
Note: a more efficient way of performing a "bulk" delete would be by providing an IQueryable
which specifies the way items should be fetched and generates a DELETE
similar to the following one:
DELETE FROM SomeTable
WHERE Id IN (SELECT Id FROM SomeTable WHERE ...)
This is faster because it does not require to load EF entities, nor create temporary table and MERGE
against it.
I have used a library for Entity Framework 6, but could not find a non-commercial one for EF Core.