37

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

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

何か案は?私は、次のことを行うことが魔法のように機能することを本当に望んでいました. (やっぱり「魔法のユニコーン」です)

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

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

4

8 に答える 8

97

使用できます

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:

チアゴのコメントで要求されたように、私は少し余分な文脈を追加します。

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

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

于 2012-01-30T11:15:16.353 に答える
24

私は最近、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();
    }
}

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

于 2014-01-09T15:18:25.667 に答える
15

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

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

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

とにかく、最初にコードを使用する場合は、POCO コンストラクターで設定するのが正しい方法です。また、いくつかの特別な場合にアプリケーションで値を設定する場合、データベースのデフォルト値にはDatabaseGeneratedOption.Identityまたはが必要なため、データベースのデフォルト値を使用できませんDatabaseGeneratedOption.Computed。これらのオプションはどちらも、データベースでのみプロパティを設定できます。

編集:

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

于 2011-12-21T20:17:31.800 に答える
6

移行を作成します。

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既存のレコードの場合、コマンドを実行する日時が設定され、新しいレコードの場合、作成日時が設定されます

于 2016-07-22T10:35:54.623 に答える
1

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

于 2011-12-25T01:42:47.173 に答える
0

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

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");
于 2016-02-17T17:26:09.940 に答える