14

Navigationsテーブルの列に。という一意の制約がありますIndex。2つの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)

ただし、Entity Frameworkは、ORMの範囲外であるため、これを行うことはできません。update彼の回答で説明されているLadislavのように、変更されたエンティティごとに順次ステートメントを実行するだけです。

もう1つの可能性はUNIQUE、データベースに制約を削除し、アプリケーションに依存してこの制約を適切に適用することです。この場合、EFは変更を適切に保存できますが、シナリオによっては、それが不可能な場合があります。

于 2012-04-19T11:12:44.560 に答える
5

いくつかのアプローチがあります。それらのいくつかは他の回答やコメントでカバーされていますが、完全を期すために、ここにリストします(これは私がブレインストーミングしたリストであり、すべてが「完全」ではない可能性があることに注意してください)。

  1. 1つのコマンドですべての更新を実行します。この例については、W0lfの回答を参照してください。
  2. 2セットの更新を実行します。1つはすべての値を目的の値の負の値にスワップし、もう1つは負の値から正の値にスワップします。これは、負の値が他の制約によって妨げられず、一時的な状態にあるもの以外のレコードが持つ値ではないという仮定に基づいて機能しています。
  3. 列を追加します(たとえば、IsUpdating)。値が変更される最初の更新セットでtrueに設定し、2番目の更新セットでfalseに戻します。IsUpdatingがtrueであるレコードを無視する、フィルター処理された一意のインデックスの一意の制約を交換します。
  4. 制約を削除し、重複する値を処理します。
于 2016-05-30T11:53:13.867 に答える