实体框架6代码优先覆盖MigrationCodeGenerator的默认值 [英] Entity Framework 6 Code first Default value overriding the MigrationCodeGenerator

本文介绍了实体框架6代码优先覆盖MigrationCodeGenerator的默认值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现的所有有关声明默认值的方法都是在Sql脚本而不是迁移代码中生成默认值。

All the approaches I've found about declaring default values, generates the default value in the Sql script, not in the migration code.

我最喜欢的是使用属性: https://stackoverflow.com/a/34894274/132942

My favorite is using attributes: https://stackoverflow.com/a/34894274/132942

[SqlDefaultValue(DefaultValue = "getutcdate()")]
public DateTime CreatedDateUtc { get; set; }



属性定义



Attribute definition

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class SqlDefaultValueAttribute : Attribute
{
    public string DefaultValue { get; set; }
}



在上下文的 OnModelCreating中添加



In the "OnModelCreating" of the context adding

modelBuilder.Conventions.Add( new AttributeToColumnAnnotationConvention<SqlDefaultValueAttribute, string>("SqlDefaultValue", (p, attributes) => attributes.Single().DefaultValue));

然后自定义 SqlGenerator 。但是我不喜欢这样,因为在生成迁移时,我没有看到所需的一切。

And then customizing the SqlGenerator. But I don't like this because I don't see when generating the migration if everything it's as I wanted.

为此,我修改了 MigrationCodeGenerator 像这样: https://stackoverflow.com/a/21024108

To do so, I modified the MigrationCodeGenerator like this: https://stackoverflow.com/a/21024108

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)
                {
                    System.Data.Entity.Infrastructure.Annotations.AnnotationValues values;
                    if (column.Annotations.TryGetValue("SqlDefaultValue", out values))
                    {
                        column.DefaultValueSql = (string)values.NewValue;
                    }
                }
            }
            else if (operation is AddColumnOperation)
            {
                ColumnModel column = ((AddColumnOperation)operation).Column;

                System.Data.Entity.Infrastructure.Annotations.AnnotationValues values;
                if (column.Annotations.TryGetValue("SqlDefaultValue", out values))
                {
                    column.DefaultValueSql = (string)values.NewValue;
                }

            }
        }

        CSharpMigrationCodeGenerator generator = new CSharpMigrationCodeGenerator();

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

但是在方法 ScaffoldedMigration >我无法获得自定义注释 SqlDefaultValue 或任何其他注释。

But in the method ScaffoldedMigration I cannot get my custom annotation SqlDefaultValue or any other annotation.

是否可以获取此注释?

推荐答案

您尚未说明如何注册您的 ExtendedMigrationCodeGenerator 使用时,您可以在 Configuration.cs 中的 Configuration 类的构造函数中执行此操作,例如:

You haven't indicated how you registered your ExtendedMigrationCodeGenerator to be used, you can do this in the constructor of the Configuration class in Configuration.cs for example:

public Configuration()
{
    AutomaticMigrationsEnabled = false;
    AutomaticMigrationDataLossAllowed = false;
    // Register the Customized Migration Generator to use
    CodeGenerator = new ExtendedMigrationCodeGenerator();
}

但也不要忘记 AlterColumnOperation

else if (operation is AlterColumnOperation alterColumnOp)
{
    ColumnModel column = alterColumnOp.Column;

    System.Data.Entity.Infrastructure.Annotations.AnnotationValues values;
    if (column.Annotations.TryGetValue("SqlDefaultValue", out values))
    {
        column.DefaultValueSql = (string)values.NewValue;
    }
}

其他情况下,您不会看到生成的输出是并且在您配置自定义 ExtendedMigrationCodeGenerator 之前在 之前生成的先前迁移中已经应用了注释。

The other scenario where you will not see a generated output is if the convention and annotations were already applied in a previous migration that was generated before you configured the custom ExtendedMigrationCodeGenerator.

调试自定义迁移逻辑并不像设置断点那样简单,因为它通常由 Migration.exe 。因此,在断点起作用之前,我们需要调用调试器,我们可以通过在要调试的位置或迁移代码生成器类的构造函数中插入以下代码来做到这一点:

Debugging custom migration logic isn't as simple as setting a breakpoint, because it is normally executed by external processes like Migration.exe. So before breakpoints will work, we need to invoke the debugger, we can do this by inserting the following code either at the point where you want to debug or in the constructor of the migration code generator class:

if (!System.Diagnostics.Debugger.IsAttached)
    System.Diagnostics.Debugger.Launch();



最好附在构造函数中,而不是靠近要调试的代码,因为我们知道构造函数应在正常条件下执行,但您的代码无法正常工作的原因可能是由于方法或代码分支根本没有执行,如果未执行,则 Launch ()命令也将不会执行。

如果使用此方法调试迁移,但不会得到调试附加对话框,然后没有检测到迁移,或者您的 ExtendedMigrationCodeGenerator 未正确注册。

If you use this method to debug the migration and you don't get the debug attach dialog then either there are no migrations detected, or your ExtendedMigrationCodeGenerator hasn't been registered correctly.

这篇关于实体框架6代码优先覆盖MigrationCodeGenerator的默认值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆