C# 在实体框架中交换具有唯一约束的值

C# 在实体框架中交换具有唯一约束的值,c#,entity-framework,C#,Entity Framework,我对导航表中名为索引的列有一个唯一的约束。我有两个导航实体,我想交换它们的索引值 当我调用db.SaveChanges时,它抛出一个异常,指示违反了唯一约束。似乎EF先更新一个值,然后更新另一个值,从而违反了约束 它不应该在事务中同时更新它们,然后在值被排序后尝试提交,并且不违反约束吗 有没有办法不使用临时值来解决这个问题?这不是EF的问题,而是SQL数据库的问题,因为更新命令是按顺序执行的。事务与此无关-所有约束都是按命令验证的,而不是按事务验证的。如果要交换唯一值,需要执行更多步骤,以便使用

我对
导航
表中名为
索引
的列有一个唯一的约束。我有两个
导航
实体,我想交换它们的
索引

当我调用
db.SaveChanges
时,它抛出一个异常,指示违反了唯一约束。似乎EF先更新一个值,然后更新另一个值,从而违反了约束

它不应该在事务中同时更新它们,然后在值被排序后尝试提交,并且不违反约束吗


有没有办法不使用临时值来解决这个问题?

这不是EF的问题,而是SQL数据库的问题,因为更新命令是按顺序执行的。事务与此无关-所有约束都是按命令验证的,而不是按事务验证的。如果要交换唯一值,需要执行更多步骤,以便使用其他虚拟值来避免这种情况。

您可以运行自定义SQL查询来交换这些值,如下所示:

update Navigation
set valuecolumn = 
        case 
            when id=1 then 'value2' 
            when id=2 then 'value1'
        end
where id in (1,2)
然而,实体框架不能做到这一点,因为它超出了ORM的范围。它只对每个修改过的实体执行顺序
update
语句,就像拉迪斯拉夫在回答中所描述的那样


另一种可能是删除数据库中的
UNIQUE
约束,并依靠应用程序正确实施该约束。在这种情况下,EF可以很好地保存更改,但根据您的情况,可能无法保存更改。

有几种方法。其中一些问题在其他答案和评论中有所涉及,但为了完整性,我将在这里列出(请注意,这只是我头脑风暴的一个列表,可能并不完全“完整”)

  • 在单个命令中执行所有更新。请参阅以获取此示例
  • 执行两组更新-一组将所有值交换为预期值的负值,另一组将它们从负值交换为正值。这是基于这样的假设,即负值不会被其他约束所阻止,并且它们不是除瞬态记录之外的记录将具有的值
  • 添加一个额外的列-例如IsUpdate-在第一组更新中将其设置为true,在第一组更新中更改值,然后在第二组更新中将其设置回false。将唯一约束替换为过滤的唯一索引,该索引将忽略IsUpdate为true的记录
  • 删除约束并处理重复的值

  • 这里需要临时值,更新是一个自包含的操作。因此,您总是会遇到约束冲突,唯一的另一种选择是禁用操作的约束。这似乎很危险,因为使用相同的伪值,或者可能是也违反约束的伪值的并发请求可能会出现问题。对于这种情况,您知道有“最佳实践”吗?您还可以删除旧记录并创建新记录。首先,我会尽量避免这种情况。在这种情况下,唯一约束不适合您的应用程序逻辑需求。这是很公平的。我将从数据库中删除唯一约束。如果有重复的,不会造成任何问题。如果有,当它们显示在导航栏上时,它们的顺序就不可靠了。设置为负数然后再返回正数的想法很聪明,为我做到了这一点。谢谢