在Entity Framework中使用唯一约束交换值

Mic*_*ray 10 c# entity-framework

我对一个Navigations名为的表的列有一个唯一约束Index.我有两个Navigation实体,我想交换它们的Index值.

当我调用db.SaveChanges它时会抛出一个异常,表明违反了一个唯一约束.似乎EF正在更新一个值然后另一个值,从而违反了约束.

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

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

Lad*_*nka 10

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


Cri*_*scu 6

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

update Navigation
set valuecolumn = 
        case 
            when id=1 then 'value2' 
            when id=2 then 'value1'
        end
where id in (1,2)
Run Code Online (Sandbox Code Playgroud)

但是,实体框架无法做到这一点,因为它超出了 ORM 的范围。它只是update为每个改变的实体执行顺序语句,就像拉迪斯拉夫在他的回答中描述的那样。

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


Sco*_*nro 6

有几种方法。其中一些已在其他答案和评论中涵盖,但为了完整起见,我将在此处列出它们(请注意,这只是我集思广益的列表,可能并不那么“完整”)。

  1. 在单个命令中执行所有更新。有关示例,请参阅W0lf 的答案。
  2. 进行两组更新 - 一组将所有值交换为预期值的负值,然后第二组将它们从负值交换为正值。这是基于以下假设:负值不会受到其他约束的阻止,并且负值不是瞬态记录以外的记录所具有的值。
  3. 添加额外的列 - 例如 IsUpdating - 在值发生更改的第一组更新中将其设置为 true,然后在第二组更新中将其设置回 false。将唯一约束交换为经过筛选的唯一索引,该索引会忽略 IsUpdating 为 true 的记录。
  4. 删除约束并处理重复值。