可以使用Entity Framework迁移将DateTime字段默认为GETDATE()吗?

ada*_*kan 33 entity-framework-4 ef-code-first ef-migrations

我将EntityFramework.Migrations(Beta 1)添加到现有的Code-First应用程序中,该应用程序正在进行一些更改(对于我从代码优先API生成的表的迁移功能和更多微调)并进入GETDATE ()场景.

我已经在我的DbContext中使用自定义初始化程序类来运行SQL脚本来设置一些字段并在我的数据库中创建索引.我的几个AlterTable脚本主要用于设置具有默认值的字段(例如某些DateTime字段设置为GETDATE()).我真的希望EntityFramework.Migrations有一个答案,因为你可以很容易地指定defaultValue,但到目前为止我没有看到一个.

有任何想法吗?我真的希望做下面的事情会神奇地起作用.(毕竟这是'神奇的独角兽')

DateCreated = c.DateTime(nullable: false, defaultValue: DateTime.Now)
Run Code Online (Sandbox Code Playgroud)

不幸的是,从逻辑上讲,它将我的默认值设置Update-Database为执行命令的时间.

giu*_*ius 92

您可以使用

DateCreated = c.DateTime(nullable: false, defaultValueSql: "GETDATE()")
Run Code Online (Sandbox Code Playgroud)

用法:

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);
 ...
Run Code Online (Sandbox Code Playgroud)

更新2012-10-10:

正如蒂亚戈在评论中提出的要求,我增加了一些额外的背景.

上面的代码是EF Migrations通过Add-Migration MyMigration在程序包管理器控制台中作为命令运行生成的迁移文件.生成的代码基于与迁移相关联的DbContext中的模型.答案建议您修改生成的脚本,以便在创建数据库时添加默认值.

您可以在此处阅读有关Entity Framework Code First Migrations的更多信息.


Jon*_*ger 23

我最近在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();
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助


Lad*_*nka 14

您必须在Up方法中使用自定义SQL脚本来设置默认值:

Sql("ALTER TABLE TableName ADD CONSTRAINT ConstraintName DEFAULT GETDATE() FOR ColumnName");
Run Code Online (Sandbox Code Playgroud)

在代码中设置默认值只允许静态值 - 没有数据库级功能.

无论如何,如果要首先使用代码,在POCO构造函数中设置它是正确的方法.此外,如果要在某些特殊情况下在应用程序中设置值,则无法在数据库中使用默认值,因为数据库中的默认值需要DatabaseGeneratedOption.Identity或者DatabaseGeneratedOption.Computed.这两个选项都只允许在数据库中设置属性.

编辑:

由于产品仍在开发中,我的答案不再有效.检查@gius答案,了解实现此要求的实际方法defaultValueSql(在EF迁移Beta 1中不可用,但已在已包含迁移的EF 4.3 Beta 1中添加).


Nin*_*ina 5

创建迁移:

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

对于现有记录,它将设置运行Update-Database命令时的日期时间,对于新记录,将设置创建的日期时间