2012-06-03 8 views
24

コードの最初の移行を使用してテーブルにnull以外の新しい列を追加すると、デフォルト値が自動的に作成されます。これは、既存の行が新しい列の値を持つ必要があるためです(nullにすることはできません)。それはいいですが、その価値がどこにでも割り当てられた後、私はもうそれを望んでいません。値が常に明示的に挿入されていることを確認したいので、nullableではありません。すべてがデフォルトで ''または0になっていれば、私は魔法の文字列を持つでしょう。だからとにかく、私は、私が感動していないという解決策ができますが、それは機能します。コードに最初に新しい列を追加した後にデフォルトの制約を削除する

カラムを追加した後、デフォルトの制約を削除します。

public override void Up() 
{ 
    AddColumn("dbo.SomeTable", "NewColumn", c => c.Int(nullable: false)); 
    Sql(Helpers.DropDefaultConstraint("dbo.SomeTable", "NewColumn")); 
} 

...

public static string DropDefaultConstraint(string table, string column) 
{ 
    return string.Format(@" 
     DECLARE @name sysname 

     SELECT @name = dc.name 
     FROM sys.columns c 
     JOIN sys.default_constraints dc ON dc.object_id = c.default_object_id 
     WHERE c.object_id = OBJECT_ID('{0}') 
     AND c.name = '{1}' 

     IF @name IS NOT NULL 
      EXECUTE ('ALTER TABLE {0} DROP CONSTRAINT ' + @name) 
     ", 
     table, column); 
} 

PROS:ヘルパーメソッドが実装されたら、私はちょうど制約を削除するために、1つの単純な行を追加する必要があります。 CONS:削除するだけでインデックスを作成する必要はないと思われます。

もう1つのアプローチは、生成されたマイグレーションを変更することです。追加するために、それをヌル可能にし、すべての値を更新してからヌル値にしないようにします。

public override void Up() 
{ 
    AddColumn("dbo.SomeTable", "NewColumn", c => c.Int()); 
    Sql("UPDATE dbo.SomeTableSET NewColumn= 1"); 
    AlterColumn("dbo.SomeTable", "NewColumn", c => c.Int(nullable: false)); 
} 

長所:単純/クリーナー

CONSだ:一時的に私の制約を変更する必要が(私はこれがトランザクションで実行され、したがって、私たちは中に不良データを許可すべきではないと仮定します)。大きなテーブルで更新が遅くなる可能性があります。

どちらの方法が好ましいですか?それとも私が行方不明になっているより良い方法はありますか?

注:列定義を一度に追加してクリーニングする場合を実証しました。以前の移行からのデフォルトをクリーンアップしているだけの場合、2番目の方法は役に立ちません。

+2

解決策1は、デフォルトの制約を削除するのに役立ちました。ありがとうございました。 – angularsen

+0

これは素晴らしいです –

答えて

10

個人的に私は最初のアプローチで何も間違っていることはわかりません。はい、ヌル以外の列を空でないデータセットに追加するには、デフォルトの制約を作成する必要があります。そして、あなたの要件に従って、新しい列が将来明示的に追加されるようにする必要がある場合は、後でその列を削除する必要があります。

このアプローチでまだ問題が発生している場合でも、問題は2番目のアプローチ以外に他の方法がない可能性が高いことです。大規模なテーブルをデフォルト値で更新するコストは、デフォルトの制約を作成して直ちにドロップするコストよりも大きいと思われます。

私も、若干の修正を検討するかもしれない:私は、エンジンによって割り当てられたデフォルトの名前を検索する騒ぎを避けるために、SQLで制約を作成することができます、このような何か:

Sql("ALTER TABLE tablename 
    ADD columnnametype NOT NULL 
    CONSTRAINT DF_tablename_columnname DEFAULT defaultvalue"); 

は(書き換えることでしたヘルパー機能を使用するため)

を単一ALTER TABLEステートメントの実行ほど自明であろう制約をドロップ:

Sql("ALTER TABLE tablename 
    DROP CONSTRAINT DF_tablename_columnname"); 

を(再び、ヘルパー関数をここで簡単に使用できます)。

しかし、すべてがC#1よりも大声で話す私のT-SQL開発者かもしれません。だから、あなたが投稿した例のようなコードでうまくいくかもしれません。

+0

私の考えを検証してくれてありがとう。私は自分自身で制約を作成することを検討しましたが、読みやすくするためにAddColumnを使いやすく、ユニークなようないくつかの制約も許しています。私はオプション1に固執することに決めました。ありがとう。 –

関連する問題