【问题标题】:Ignore duplicate entries and commit successful ones on DbContext.SaveChanges() in EF Core忽略重复条目并在 EF Core 中的 DbContext.SaveChanges() 上提交成功的条目
【发布时间】:2020-05-14 16:40:03
【问题描述】:

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

例如:

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

我添加的实体有两个主键(复合主键),当我将它们添加到 DbContext 时,这些键已经填充到实体集合中(即我自己设置键 - 没有“自动增量”或类似数据库生成密钥的东西)

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

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

谢谢

【问题讨论】:

  • 使用 Dapper 很简单,因为您可以控制 sql。

标签: mysql asp.net-core dbcontext ef-core-2.2 entity-framework-core-2.2


【解决方案1】:

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

您似乎已经决定:您想放弃该操作。

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

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

使用这个库(这是一个已知的库,Microsoft 已经将其称为 EF Core 工具:https://docs.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,但它会保持您的数据完好无损。

【讨论】:

  • 不幸的是,库 "目前仅支持 MsSQL"
  • MySQL 的机制也是一样的。无论如何,您最终都会处理原始 SQL MERGE,但我提到示例库仅在 MsSQL 下工作。谢谢。
  • 感谢您的回复 Razvan。我会调查那些图书馆。我想要删除会导致添加具有重复 ID 的行的操作的原因是因为这是针对聊天应用程序的,并且我将消息 ID 插入到表中以指定是否读取了消息以及由谁读取。每次客户端应用程序从 API(从 MySQL 数据库中获取)请求新消息时,API 也会将这些消息 ID 插入到所述表中,指示消息已被读取以及由谁读取。如果客户端再次请求相同的消息列表,我不想将这些记录 id 重新插入到表中
  • 这个表是一个简单的表,包含三个字段:messageId、userId 和 readDate。 messageId 和 userId 共同构成主键。如果用户两次阅读相同的消息,我不想在此表中插入两条相同的记录。用户第一次阅读消息是我想要存储的全部内容。
  • 听起来像是一个不错的候选者,它可以让你进入原始 sql 合并,你将在其中执行以下操作:当匹配时,更新 SET A.ID=A.ID 或(在 mysql 中你有) INSERT INTO t1 (MessageId,UserId,ReadDate) VALUES (1, 2, Date) ON DUPLICATE KEY UPDATE MessageId=MessageId; dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-31
  • 1970-01-01
  • 2019-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多