实体框架6代码优先覆盖MigrationCodeGenerator的默认值 [英] Entity Framework 6 Code first Default value overriding the 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 $ c之类的外部进程执行。 $ c>。因此,在断点起作用之前,我们需要调用调试器,我们可以通过在要调试的位置或迁移代码生成器类的构造函数中插入以下代码来做到这一点:
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屋!