次のようなテーブルのいくつかの行の追加データを格納するテーブルがあります。
public class QuoteExtra
{
[Key]
public int QuoteId { get; set; }
// More fields here
}
PKを明示的に設定したこのテーブルに行を追加できるようにしたいと思います。
上記のようにそのままにしておくと、値を設定して行を送信すると、値が破棄され、データベースから自動生成された値に置き換えられます(そして、列は実際のスキーマでIdentity列として定義されます)。
これは正しい解決策のようです:
public class QuoteExtra
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int QuoteId { get; set; }
// More fields here
}
しかし、これは代わりに私に例外を与えます:
IDENTITY_INSERTがOFFに設定されている場合、テーブル 'EnumTest'のID列に明示的な値を挿入できません。
では、EFで主キーの値を設定できるようにするには、クラスをどのように記述すればよいでしょうか。
編集:
次のコードベースの移行を追加して、IDENTITY_INSERTをONに設定してみました。
public override void Up()
{
Sql("SET IDENTITY_INSERT QuoteExtra ON");
}
実行して再試行しましたが、上記と同じ例外が発生しました。奇妙なことに、データベースはこの設定を反映し、SQLを直接実行すると、主キーに任意の値を挿入できます。そのため、Entity Framework自体がこのルールを適用しており、IDENTITY_INSERTが含まれていないことの認識を怠っています。事実はオフに設定されています。 EF自体のどこかに設定する必要がありますか?
編集2:
IDENTITY_INSERTを誤解しました。私はそれをそのテーブルにいつまでもオンのままにしておくと仮定しました。実際、それは「セッション」の間存続します。たとえば、Migrationで設定することは、それが存続することを意味します...そのMigrationが実行されている限り存続し、EFを使用した後の.Add() 、これはなぜ私がまだその例外を受け取ったのかを説明しています-DBは実際にはEFではなく例外のソースです。 IDENTITY_INSERTはセッションごとに最大1つのテーブルに制限されているため、これを行うのはかなり非効率的な方法です。そもそもIdentity PK列を作成しない方が、より良いルートのように見えます。
これは、アイデンティティ自動インクリメントを有効にせずにPKを作成する適切な方法です。
public class QuoteExtra
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int QuoteId { get; set; }
// More fields here
}
ただし、EF Migrationsが既にテーブルを作成した後でDatabaseGenerated(DatabaseGeneratedOption.None)]を追加すると、静かにテーブルに対して何も行われません。これがシナリオの場合は、テーブルを削除するために手動の移行を追加する必要があります。
add-migration RecreateQuoteExtra
そして移行では:
public override void Up()
{
DropTable("QuoteExtra");
}
EF自動移行は、Identity制約なしでテーブルを自動的に再作成します。これにより、IDENTITY_INSERT ONなどの特別なコマンドを実行しなくても、いつでもPK値を設定できます。
これを行うための非破壊的な方法はEF7(「データモーション」)に含まれているようですが、既存のデータを失わないようにしたい場合は、移行中に手動で大量のSQLを作成して一時テーブルを作成し、データを移動することができます。テーブルに。
編集:シナリオによっては、EF Migrationsがテーブルを再作成しない場合があります-クラスがすでに存在し、DbContextにすでに追加されている場合は、それをドロップしてそのままにします。つまり、手動の移行では、ドロップするだけでなく、テーブル。 EF Migrationsがadd-migrationから生成するスキャフォールドコードはこれらのステートメントを作成するので、大したことではありませんが、問題をチェックするためのコードが少し多くなります。
これは正しい解決策ですが、新しいテーブルに対してのみです。既存のテーブルのデータベース生成オプションを変更した場合、EF移行ではこの変更を実行できず、QuoteId
列はデータベースでIdentity
としてマークされます。
ヒントでこの問題を解決できなかったため、データベース全体を再作成しようとしましたが、うまくいきませんでした。
これを修正するには、列の最初の(!)作成時にidentity:trueプロパティを削除する必要があります(例:Initial-Migration)。
多分それは誰かを助けるでしょう。