我有一个 ASP .Net Core 2.2 Web API。在我的一个控制器操作中,我向 MySQL 数据库表添加了一堆行(我使用的是 Pomelo)。
举个例子:
_dbContext.AddRange(entities);
_dbContext.SaveChanges();
我要添加的实体有两个主键(复合主键),并且当我将它们添加到 DbContext 时,这些键已经填充在实体集合中(即我自己设置键 - 没有“自动增量”或任何内容)就像数据库生成密钥一样)
如果我添加的任何实体已经存在于数据库中,就重复的主键而言,那么显然 SaveChanges() 会抛出异常,并且整个事务会回滚。
有没有办法告诉 EF Core 忽略失败的实体?即忽略数据库中已存在的实体,并提交成功的实体(即数据库中不存在的实体)?而不是当前的行为是抛出异常并回滚整个事务?
谢谢
您似乎遇到了业务问题。首先,您需要决定当您已经拥有一个具有相同 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,但它会让您的数据完好无损。