web-dev-qa-db-ja.com

最初にコードを使用して整数主キーのIDを無効にする(自動インクリメント)

ASP.NET MVC 3アプリケーションでコードファーストアプローチを使用し、モデル内のすべての整数主キー(public int Id { get; set; })は、デフォルトで自動インクリメントのIDとして設定されます。これを無効にして、主キーの整数を手動で入力する方法を有効にする方法は?

実際の状況では、Id整数には特別な意味があるので、作成時に選択可能にし、後で編集できるようにします。作成時に整数が指定されていない場合、自動インクリメントされるのが理想的です。そうでない場合は、指定された値が使用されます。しかし、編集可能なプライマリフィールドが私の主なニーズです。 ASP.NET MVC 3でこれをエレガントに行う方法はありますか?

38
gw0

次のデータ注釈オプションを使用します。

  • [System.ComponentModel.DataAnnotations.KeyAttribute()]
  • [System.ComponentModel.DataAnnotations.DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None)]
51
Greg

FluentMappingを使用できます:

modelBuilder.Entity<*entityname*>().Property(m => m.*fieldname*)
             .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
27
William Haack

EntityFramework Core 2.0でFluent APIを使用する場合は、次のように記述します。

modelBuilder.Entity<*myEntity*>()
  .Property(e => e.*myFieldname*)
  .ValueGeneratedNever();
3
René

属性を使用:

public class MessageSubject
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int Id { get; set; }
        public string Title { get; set; }
        public string Comment { get; set; }
        public bool BuildIn { get; set; }
    }
2
pixparker

最新の承認済みEntityFramework.dllバージョン5.0.0をインストールしました。

ただし、v4.0.30319のランタイムバージョンと4.4.0.0のバージョンがあるため、半分の時間で混乱しますが、検索で参照したWebサイトからは確実です(「パッケージマネージャーVS「ツール|ライブラリパッケージマネージャー|パッケージマネージャーコンソール」内のメニューからアクセスし、「PM>」プロンプトで入力する「コンソール」。「インストールパッケージEntityFramework [オプション:最新のプレリリースのバージョン番号または-Pre (ベータ版)] ")5.0.0でした。

...、使用できる属性「System.CompnentModel.DataAnnotations.DatabaseGenerated(Computed、Identity or None)(以前のバージョン)または[...]。Schema.DatabaseGenerated(最新バージョン)」があります。したがって、この属性を使用するか、上記のように流ideaなマッピングアイデアを使用し(William Haack(Remo Gloorによる編集))、最初にコードを作成しない場合(生産を変更する場合)、上記の(Adam Tuliperによる) 1回限りのスクリプトを実行して、ID挿入をオフにします。さらに、IDを指定しない場合は、コードでテーブルのMAX(ID)+ 1を取得する(およびマルチユーザー環境での同時実行の問題に留意する)か、トリガーでID挿入をシミュレートできます。あるいは、式のように穴を埋めたい場合は、挿入された行をインターセプトしてID列が設定されているかどうかを確認することで、おそらくトリガーでこれを行うことができます。そうでない場合は、挿入を続行し、最初に値を設定します。穴を塞ぐアプローチの1つは、そのトリック(覚えていないWebサイトで見たので、ここでは少し推測します)を使用することです。テーブルに行番号の単一列を使用して、最初に使用可能な未使用のID番号を検索します(つまり、ターゲットテーブルのメンバーではない最初の行番号を検索します)。

SQL Server 2005以降:

CREATE TRIGGER updInsYourTable_PlugHolesOnIDIfNull 
ON YourTable
FOR update, insert AS
BEGIN
    DECLARE @ID INT
    SELECT @ID = ID FROM INSERTED
    IF @ID IS NULL
    BEGIN
        ;WITH CTE_StagedNumbers AS
        (
            SELECT ROW_NUMBER() OVER (ORDER BY o.object_id) AS NextFreeIdentity
            FROM (  SELECT object_id FROM sys.objects
                 -- UNION ALL 
                 -- SELECT object_id FROM sys.objects
                 /* NB: Here if sys.objects is not larger enough say on a small schema 
                    configured database then use a different table otherwise you can 
                    always union all on the same table as many times as you want to 
                    double, triple etc. its size. */
                 )  o
        )
        UPDATE YourTable
        SET ID = (
                    SELECT TOP 1 NextFreeIdentity
                    FROM CTE_StagedNumbers
                    WHERE NextFreeIdentity NOT IN (SELECT ID FROM YourTable)
                 )
        WHERE ID IS NULL
    END
END
GO

CTE_StagedNumbersは必要ありません。強調のためだけにあり、主なトリックは必ずしも行番号の設定ではありませんが、1つの整数だけで永続的なステージングテーブル(たとえばStagedNumbers)を設定する場合自動識別のない列(たとえば、NextFreeIdentity INT NOT NULL PRIMARY KEY)、(脇:NB:ID列のYourTable定義は、afterトリガーを使用しているため、nullを受け入れる必要があります)上記の手法では、CTEを完全に削除し、最終選択のCTE_StagedNumbersをStagedNumbersに置き換えます。これが最も効率的です。

2
Glen

これがデータベースのIDフィールドである場合は禁止です。データベース側でID挿入をオフに設定することでできますが、レコードを一括挿入しない限り、実行することはできません。これをIDとして使用したくない場合は、その列のDBでIDオプションをfalseに設定します。

1