14

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

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

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

有没有办法在不使用临时值的情况下解决这个问题?

4

3 回答 3

12

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

于 2012-04-19T11:05:48.210 回答
6

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

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

但是,实体框架不能这样做,因为它超出了 ORM 的范围。update它只是为每个更改的实体执行顺序语句,就像 Ladislav 在他的回答中描述的那样。

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

于 2012-04-19T11:12:44.560 回答
5

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

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