20

次のようなテーブルのいくつかの行の追加データを格納するテーブルがあります。

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 を誤解しました。一度設定すると、そのテーブルで無期限にそのままになっていると思いました。実際、それは「セッション」である限り存続します。つまり、たとえば、移行で設定すると、存続することを意味します...その移行が実行され、EF を使用した後の .Add() のような将来の接続に影響を与えない限り、これは私がまだその例外を受け取った理由を説明しています-DBは実際にはEFではなく例外の原因です。IDENTITY_INSERT はセッションごとに最大で 1 つのテーブルに制限されているため、これを行うにはかなり非効率的な方法です。最初に Identity PK 列を作成しない方がよい方法のように思えます。

4

3 に答える 3

34

これは、ID自動インクリメントを有効にせずに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自動移行では、ID制約なしでテーブルが自動的に再作成されます。これにより、IDENTITY_INSERT ONなどの特別なコマンドを実行しなくても、いつでもPK値を設定できます。

これを行うためのより破壊的でない方法はEF7( "Data Motion")で提供されているようです。または、既存のデータの損失を回避したい場合は、移行時に手動のSQLを大量に記述して、一時テーブルを作成し、データを移動することができます。テーブルで。

編集:シナリオによっては、EF Migrationsがテーブルを再作成しない場合があります-クラスがすでに存在し、DbContextにすでに追加されている場合は、それを削除してそのままにします。つまり、手動移行では、削除するだけでなく、作成する必要があります。テーブル。EF Migrationsがadd-migrationから生成するスキャフォールドコードがこれらのステートメントを作成するため、大したことではありませんが、問題をチェックするためのコードはもう少し多くなります。

于 2013-03-19T22:20:26.657 に答える
4

これは正しい解決策ですが、新しいテーブルに対してのみです。既存のテーブルのデータベース生成オプションを変更すると、EF 移行はこの変更を実行できず、データベース内のQuoteId列は引き続きマークさIdentityれます。

于 2013-03-19T20:25:19.513 に答える
1

あなたのヒントでこの問題を解決できなかったので、データベース全体を再作成しようとしましたが、うまくいきませんでした。

これを修正するには、列の最初の (!) 作成でidentity: trueプロパティを削除する必要があります (例: Initial-Migration)。

多分それは誰かを助けるでしょう..

于 2014-03-20T14:19:03.117 に答える