2013-02-12 13 views
29

私はEF5コード初心者です。私はEF5コード初心者です。EF5コードファースト - マイグレーションによるカラムタイプの変更

私は当初

public class Person { 
    public int Id { get; set; } 
    public string FirstName { get; set;} 
    public string Surname {get;set;} 
    public string Location {get;set;} 
} 

のようなものを見て、私は私が上に立ち往生少しMVCアプリケーションを使用して、いくつかのレコードを追加モデルを作成しました。

今私は、列挙に何かLocation列を変更したい:私は

AlterColumn("dbo.People", "Location", c => c.Int(nullable: false)); 

が、私は更新データベースを実行すると:私は私が得る新しい移行を追加すると

public class Person { 
    public int Id { get; set; } 
    public string FirstName { get; set;} 
    public string Surname {get;set;} 
    public Locations Location {get;set;} 
} 

public enum Locations { 
    London = 1, 
    Edinburgh = 2, 
    Cardiff = 3 
} 

をエラーが発生する

Conversion failed when converting the nvarchar value 'London' to data type int. 

alterステートメントを実行する前にテーブルを切り捨てる方法はありますか?

私はデータベースを開いて手動で行うことができますが、よりスマートな方法はありますか?

+2

私は変換が、このページの回答の一部を以下の前に、エンティティフレームワークによって自動的に処理されている場合、彼らは見る同様の位置にある開発者のためのお勧め:

は、まずSql()コマンドと、その後AlterColumn()を実行してみてください。たとえば、文字列と小数点の間の変換を処理していることがわかりました。私の助けを借りずに - Add Migrationが生成した移行はうまく動作します。明らかに、ローカル/テストのデータベースで試してから、実稼働環境に適用してください! – pipedreambomb

答えて

45

最もスマートな方法はおそらくタイプを変更しないことです。更新ステートメントを使用して

  1. は、元の列からのデータを引き継ぐためにあなたの新しいタイプ
  2. 使用Sql()に新しい列を追加します。これを行うために必要がある場合、私はあなたが以下の手順を実行することをお勧めしたいです
  3. 古い列
  4. これは、すべて同じ移行で行うことができる新しいカラム

の名前を変更を外し、正しいSQLスクリプトが作成されます。データを破棄する場合は、手順2はスキップできます。それを引き継ぐ場合は、適切なステートメントを追加します(switchステートメントも含めることができます)。

残念ながら、コード・ファースト・マイグレーションはこれを達成するためのより簡単な方法を提供しません。

AddColumn("dbo.People", "LocationTmp", c => c.Int(nullable: false)); 
Sql(@" 
    UPDATE dbp.People 
    SET LocationTmp = 
     CASE Location 
      WHEN 'London' THEN 1 
      WHEN 'Edinburgh' THEN 2 
      WHEN 'Cardiff' THEN 3 
      ELSE 0 
     END 
    "); 
DropColumn("dbo.People", "Location"); 
RenameColumn("dbo.People", "LocationTmp", "Location"); 
+0

簡単な注意:一時的な列を使用することは、 'Down()'を移行するときにこれを行うための唯一の方法です。スキーマの更新は 'Sql()'コマンドを含むトランザクション内で実行されているように見えます。これは 'Integer'値から' String'への列更新が同じエラーメッセージで失敗します。 'AlterColumn()の代わりに'を使用します。これは、Sql() 'AFTER' AlterColumn() 'を実行してもこれです。 – InteXX

12

@ JustAnotherUserYouMayKnowの回答に基づいていますが、より簡単に:ここで

は、サンプルコードです。

Sql(@" 
    UPDATE dbo.People 
    SET Location = 
     CASE Location 
      WHEN 'London' THEN 1 
      WHEN 'Edinburgh' THEN 2 
      WHEN 'Cardiff' THEN 3 
      ELSE 0 
     END 
    "); 
AlterColumn("dbo.People", "Location", c => c.Int(nullable: false)); 
+1

私はそれがマークされた答えよりも好きです:それは一時的な列を必要としません。 – Marcel

関連する問題