忽略重复条目并在 EF Core 中的 DbContext.SaveChanges() 上提交成功条目

问题描述 投票:0回答:1

我有一个 ASP .Net Core 2.2 Web API。在我的一个控制器操作中,我向 MySQL 数据库表添加了一堆行(我使用的是 Pomelo)。

举个例子:

_dbContext.AddRange(entities);
_dbContext.SaveChanges();

我要添加的实体有两个主键(复合主键),并且当我将它们添加到 DbContext 时,这些键已经填充在实体集合中(即我自己设置键 - 没有“自动增量”或任何内容)就像数据库生成密钥一样)

如果我添加的任何实体已经存在于数据库中,就重复的主键而言,那么显然 SaveChanges() 会抛出异常,并且整个事务会回滚。

有没有办法告诉 EF Core 忽略失败的实体?即忽略数据库中已存在的实体,并提交成功的实体(即数据库中不存在的实体)?而不是当前的行为是抛出异常并回滚整个事务?

谢谢

mysql asp.net-core dbcontext ef-core-2.2 entity-framework-core-2.2
1个回答
5
投票

您似乎遇到了业务问题。首先,您需要决定当您已经拥有一个具有相同 id 的实体并且有人尝试插入具有相同 id 的新实体(新信息)时会发生什么。

看来您已经决定:您想放弃该操作。

这在某种程度上是不寻常的,因为如果您从该 API 的客户端收到一些关于数据库中已存在的实体的新数据 -> 这看起来更像是更新。

存在一些可以执行类似操作的库:https://github.com/borisdj/EFCore.BulkExtensions(目前仅适用于 MsSQL)

编辑: 2024 年,BulkExtensions 现在可与 SQLServer、PostgreSQL、MySQL 和 SQLite 配合使用。

使用此库(这是一个已知的库,并且 Microsoft 已将其称为 EF Core 工具:https://learn.microsoft.com/en-us/ef/core/extensions/),您有可能至:

  • 如果找到具有相同 id 的实体,则插入或更新所有数据(所有列)(Upsert):

    context.BulkInsertOrUpdateAsync(entitiesList);

  • 将数据库中的实体与您从客户端收到的任何实体同步:

    context.BulkInsertOrUpdateOrDeleteAsync(entitiesList);

很可能您找不到已经为您的案例实现的东西,但您可以使用以下方法调整此库:

BulkInsertOrDropAsync 

这会做类似的事情:

WHEN MATCHED THEN UPDATE SET A.ID=A.ID --The ID's are already the same so nothing will happen
WHEN NOT MATCHED THEN INSERT(A.ID,A.NAME,A.CODE,A.DESCRIPTION) 

这并不是真正的 DROP,但它会让您的数据完好无损。

© www.soinside.com 2019 - 2024. All rights reserved.