web-dev-qa-db-ja.com

Entity Framework MigrationsでDateTimeフィールドをGETDATE()にデフォルト設定できますか?

EntityFramework.Migrations(ベータ1)をいくつかの変更(移行機能と、コードファーストAPIから生成するテーブルの微調整の両方)を行っている既存のCode-Firstアプリに追加し、GETDATEを実行しました。 ()シナリオ。

私はすでにDbContextでカスタム初期化クラスを使用してSQLスクリプトを実行し、いくつかのフィールドを設定してデータベースにインデックスを作成していました。 AlterTableスクリプトのほんの一握りは、デフォルト値(GETDATE()に設定されている特定のDateTimeフィールドなど)でフィールドをセットアップするためだけのものです。 defaultValueを簡単に指定できるため、EntityFramework.Migrationsがこれに対する答えを持っていることを本当に望んでいましたが、今のところ表示されていません。

何か案は?次のことを行うことが魔法のように機能することを本当に望んでいました。 (結局「魔法のユニコーン」です)

DateCreated = c.DateTime(nullable: false, defaultValue: DateTime.Now)

残念ながら、論理的には、デフォルト値をUpdate-Databaseコマンドが実行されました。

33
adammokan

デフォルト値を設定するには、UpメソッドでカスタムSQLスクリプトを使用する必要があります。

Sql("ALTER TABLE TableName ADD CONSTRAINT ConstraintName DEFAULT GETDATE() FOR ColumnName");

コードでデフォルト値を設定すると、静的な値のみが許可され、データベースレベルの関数は許可されません。

とにかくPOCOコンストラクターで設定するのは、最初にコードを使用する場合の正しい方法です。データベースのデフォルト値にはDatabaseGeneratedOption.IdentityまたはDatabaseGeneratedOption.Computed。これらのオプションは両方とも、データベースでのみプロパティを設定できます。

編集:

製品はまだ開発中であるため、私の答えはもはや有効ではありません。 defaultValueSqlを使用してこの要件を実現する実際の方法については、@ giusの回答を確認してください(EF Migrations Beta 1では使用できませんでしたが、既に移行を含むEF 4.3 Beta 1で追加されました)。

14
Ladislav Mrnka

使用できます

DateCreated = c.DateTime(nullable: false, defaultValueSql: "GETDATE()")

使用法:

public partial class MyMigration : DbMigration
{
    public override void Up()
    {
        CreateTable("dbo.Users",
            c => new
                {
                    Created = c.DateTime(nullable: false, defaultValueSql: "GETDATE()"),
                })
            .PrimaryKey(t => t.ID);
 ...

2012-10-10を更新:

Thiagoのコメントで要求されているように、もう少しコンテキストを追加します。

上記のコードは、パッケージマネージャーコンソールでAdd-Migration MyMigrationをコマンドとして実行することにより、EF Migrationsによって生成された移行ファイルです。生成されたコードは、移行に関連付けられたDbContextのモデルに基づいています。答えは、データベースの作成時にデフォルト値が追加されるように、生成されたスクリプトを変更することを示唆しています。

Entity Framework Code First Migrationsの詳細については、こちらをご覧ください こちら

92
gius

私は最近、EF6でこの問題に遭遇しました(まだ修正されていないため)。 Migrationクラスを手動で変更せずに行う最も簡単な方法は、ConfigurationクラスのCodeGeneratorをオーバーライドすることです。

MigrationCodeGeneratorを実装するクラスを作成し、Generateメソッドをオーバーライドすることにより、すべての操作を反復処理し、必要な変更を適用できます。

変更が完了したら、CSharpMigrationCodeGeneratorを初期化してデフォルト値を返すことができます。

public class ExtendedMigrationCodeGenerator : MigrationCodeGenerator
{
    public override ScaffoldedMigration Generate(string migrationId, IEnumerable<MigrationOperation> operations, string sourceModel, string targetModel, string @namespace, string className)
    {
        foreach (MigrationOperation operation in operations)
        {
            if (operation is CreateTableOperation)
            {
                foreach (var column in ((CreateTableOperation)operation).Columns)
                    if (column.ClrType == typeof(DateTime) && column.IsNullable.HasValue && !column.IsNullable.Value && string.IsNullOrEmpty(column.DefaultValueSql))
                        column.DefaultValueSql = "GETDATE()";
            }
            else if (operation is AddColumnOperation)
            {
                ColumnModel column = ((AddColumnOperation)operation).Column;

                if (column.ClrType == typeof(DateTime) && column.IsNullable.HasValue && !column.IsNullable.Value && string.IsNullOrEmpty(column.DefaultValueSql))
                    column.DefaultValueSql = "GETDATE()";
            }
        }

        CSharpMigrationCodeGenerator generator = new CSharpMigrationCodeGenerator();

        return generator.Generate(migrationId, operations, sourceModel, targetModel, @namespace, className);
    }
}

internal sealed class Configuration : DbMigrationsConfiguration<Project.Models.Context.DatabaseContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
        MigrationsDirectory = @"Migrations";
        this.CodeGenerator = new ExtendedMigrationCodeGenerator();
    }
}

これが役立つことを願っています

23
JonnySchnittger

移行を作成します。

public partial class Table_Alter : DbMigration
{
    public override void Up()
    {
        AddColumn("dbo.tableName", "columnName", 
           c => c.DateTime(nullable: false, defaultValueSql: "GETDATE()"));
    }

    public override void Down()
    {
        DropColumn("dbo.tableName", "columnName");
    }
}

既存のレコードの場合、Update-Databaseコマンド、新規レコードの場合、作成日時が設定されます

5
Nina

または、エンティティが共通のインターフェイスから継承する場合、DbContextのSaveChangesメソッドをオーバーライドし、その時点でプロパティを設定または更新できます(作成日および最終変更日に最適)

1
Betty

改善:制約が存在するかどうかを確認します。

Sql(@"
if not exists (
    select *
      from sys.all_columns c
      join sys.tables t on t.object_id = c.object_id
      join sys.schemas s on s.schema_id = t.schema_id
      join sys.default_constraints d on c.default_object_id = d.object_id
    where 
      d.name = 'DF_ThubOutputEmail_Created'
)
begin
    ALTER TABLE dbo.ThubOutputEmails ADD CONSTRAINT DF_ThubOutputEmail_Created default getdate() for Created;
end");
0
Martin Staufcik

これが最も簡単な方法です。

最初の追加 _DatabaseGeneratedOption.Computed_ DataAnnotionをプロパティに

そして今、あなたはde SqlServerMigrationSqlGenaratorを修正し、Genarateメソッドをオーバーライドし、DefaultValueSql = "GETDATE()" or "GETUTCDATE()";を設定することができます

0
Fesaro