簡體   English   中英

如何刪除 Entity Framework Core 中的多行?

[英]How do I delete multiple rows in Entity Framework Core?

我需要使用 Entity Framework Core 從數據庫中刪除多行。

此代碼不起作用:

foreach (var item in items)
{
    myCollection.Remove(item);
}

因為我在第一個對象之后收到錯誤“InvalidOperationException:集合已修改;枚舉操作可能無法執行”。 換句話說, .Remove只刪除一個對象。

Entity Framework Core 沒有.RemoveRange ,所以我不知道如何執行此操作。

為了保持與各種數據庫提供程序的最大兼容性,我不希望調用 context.Database.ExecuteSqlCommand("delete from physical_table where...")。 有合適的解決方案嗎? 謝謝!

因為我在第一個對象之后收到錯誤“InvalidOperationException:集合已修改;枚舉操作可能無法執行”。 換句話說, .Remove 只刪除一個對象。

這與 EF Core 無關,是的, .Remove()僅刪除一個對象。 但是,您正在嘗試修改正在迭代的集合。 很多方法可以做到這一點,但這不是一條好的路線。

Entity Framework Core 沒有 .RemoveRange,所以我不知道如何執行此操作。

肯定至少有幾種簡單的方法可以刪除 EF Core 中的多個記錄。 而且,EF Core 確實有一個RemoveRange()方法 - 它是DbSet<TEntity>上的一個方法,請參閱API 文檔中的此處(如上面的評論中所述)。

幾個選項:

  1. 如果myCollection是屬於DbSet<TEntity> ,那么像這樣的簡單調用就可以解決問題:

     _dbContext.MyEntities.RemoveRange(myCollection); _dbContext.SaveChanges();
  2. 如果myCollection實際上是您查詢的實體的導航屬性,您可以在集合上調用.Clear()而不是迭代和調用.Remove()

     var myParentEntity = _dbContext.MyParentEntities .Include(x => x.MyChildrenEntities) .Single(x => x.Id == id); myParentEntity.MyChildrenEntities.Clear(); _dbContext.SaveChanges();

正如上面所評論的,您的問題缺少很多上下文 - 應該發布更完整的代碼。 我只是在黑暗中嘗試了幾次,讓您開始使用 EF Core!

如果您想在某個任意過濾器上刪除許多項目(讀取數百個或更多),最有效的方法是所謂的“批量刪除”。 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 的非商業庫。

你可以做這樣的事情

[HttpDelete("{id}")]
public async Task<ActionResult<string>> DeleteAsset(int id)
{
    _db.Assets.Remove(_db.Assets.Find(id));
    await _db.SaveChangesAsync();
    // Đi tìm trang table asset_image
    List<AssetImage> assetImageList = _db.AssetImages.Where(x => x.AssetId == id).ToList();
    foreach(AssetImage assetImageItem in assetImageList)
    {
        _db.AssetImages.Remove(assetImageItem);
        _db.SaveChangesAsync();
    }
    return Ok("ok");
}

我創建了一個庫,用於在 EF Core 5 上通過往返來批量刪除或更新記錄。

示例代碼如下:

await ctx.DeleteRangeAsync(b => b.Price > n || b.AuthorName == "zack yang");

await ctx.BatchUpdate()
.Set(b => b.Price, b => b.Price + 3)
.Set(b=>b.AuthorName,b=>b.Title.Substring(3,2)+b.AuthorName.ToUpper())
.Set(b => b.PubTime, b => DateTime.Now)
.Where(b => b.Id > n || b.AuthorName.StartsWith("Zack"))
.ExecuteAsync();

Github 存儲庫

圖書館報告

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM