You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用筛选唯一索引时,如何管理EF Core的更新顺序?

EF Core 筛选唯一索引更新顺序引发的唯一约束冲突问题

问题描述

我定义了一个筛选唯一索引,代码如下:

builder
    .HasIndex(e => new { e.UserId, e.IsDefault })
    .HasFilter($"[{nameof(MyEntity.IsDefault)}] = 1")
    .IsUnique()
    .HasDatabaseName($"UX_{nameof(MyEntity)}_{nameof(MyEntity.UserId)}_{nameof(MyEntity.IsDefault)}");

对应的SQL语句为:

CREATE UNIQUE NONCLUSTERED INDEX [UX_MyEntity_UserId_IsDefault] 
ON [dbo].[MyEntity] ([UserId] ASC,
                     [IsDefault] ASC)
WHERE ([IsDefault] = (1))

该索引要求每个UserId仅允许一条IsDefault为true的记录,因此更新顺序必须是先将原默认记录设为false,再将目标记录设为true。但EF Core无法识别该筛选条件的约束逻辑,生成的更新语句顺序错误,频繁触发以下报错:

Cannot insert duplicate key row in object 'dbo.MyEntity' with unique index 'UX_MyEntity_UserId_IsDefault'

示例重现

数据库初始数据

IdUserIdIsDefault
150
251
350

代码逻辑

var parent = await parentEfRepository.GetByIdAsync(5, cancellationToken);

var newDefaultChild = parent.Children.Where(c => ...);
newDefaultChild.SetAsDefault();

await context.SaveChangesAsync(cancellationToken);

SetAsDefault()方法会将该用户下其他子记录的IsDefault设为false,最终仅保留目标记录为true。但调用SaveChanges()时,EF Core会先更新目标记录为true,此时数据库中临时存在两条IsDefault=1的记录,触发唯一约束报错。

已尝试用EF Core拦截器解决,但实现过于繁琐,寻求更简洁的解决方案。

环境信息

  • EF Core版本:8.0.11
  • 数据库提供程序:Microsoft.EntityFrameworkCore.SqlServer
  • 目标框架:.NET 8.0
  • 操作系统:Windows
  • IDE:Rider

内容的提问来源于stack exchange,提问作者Seb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 05:02:13