您可以通过在类的构造函数中MigrationSqlGenerator
调用DbMigrationsConfiguration.SetSqlGenerator()方法DbMigrationsConfiguration
,传递数据库提供程序名称(例如,"System.Data.SqlClient"
对于SQL Server)和MigrationSqlGenerator
要用于该数据库提供程序的实例,来覆盖Entity Framework使用的。
考虑您链接到的工作项中的示例:
public class MyEntity
{
public int Id { get; set; }
[Required]
[MinLength(5)]
public string Name { get; set; }
}
假设MyEntity
已经生成的表,并且使用该Add-Migration
命令添加了Name
字段。
默认情况下,支架式迁移为:
public partial class AddMyEntity_Name : DbMigration
{
public override void Up()
{
AddColumn("dbo.MyEntity", "Name", c => c.String(nullable: false));
}
public override void Down()
{
DropColumn("dbo.MyEntity", "Name");
}
}
请注意,脚手架没有为生成任何东西MinLengthAttribute
。
要使EF传达最小长度要求,您可以指定一个属性到列的注释约定。如该文档页面上AnnotationValues
所述,默认SQL生成器会忽略任何内容。
在您的DbContext的OnModelCreating()覆盖范围内,添加以下内容:
modelBuilder.Conventions.Add(new AttributeToColumnAnnotationConvention<MinLengthAttribute, Int32>("minLength", (property, attributes) => attributes.Single().Length));
添加完之后,您可以通过运行重新生成支架式迁移Add-Migration -Force AddMyEntity_Name
。现在,脚手架迁移是:
public partial class AddMyEntity_Name : DbMigration
{
public override void Up()
{
AddColumn("dbo.MyEntity", "Name", c => c.String(nullable: false,
annotations: new Dictionary<string, AnnotationValues>
{
{
"minLength",
new AnnotationValues(oldValue: null, newValue: "5")
},
}));
}
public override void Down()
{
DropColumn("dbo.MyEntity", "Name",
removedAnnotations: new Dictionary<string, object>
{
{ "minLength", "5" },
});
}
}
假设像链接的工作项中一样,您想要生成一个约束以检查调整后的Name
值是否大于minLength(在这种情况下为5)。
您可以从创建一个MigrationSqlGenerator
扩展的自定义开始,SqlServerMigrationSqlGenerator
并调用SetSqlGenerator()来安装该自定义MigrationSqlGenerator
:
internal class CustomSqlServerMigrationSqlGenerator : SqlServerMigrationSqlGenerator
{
protected override void Generate(AddColumnOperation addColumnOperation)
{
base.Generate(addColumnOperation);
}
}
internal sealed class Configuration : DbMigrationsConfiguration<DataContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
SetSqlGenerator("System.Data.SqlClient", new CustomSqlServerMigrationSqlGenerator());
}
protected override void Seed(DataContext context)
{
//...
}
}
现在,它CustomSqlServerMigrationSqlGenerator
覆盖了Generate(AddColumnOperation)方法,但是只是调用了基本实现。
如果您查看的文档AddColumnOperation
,将会看到两个重要的属性Column
和Table
。Column
是ColumnModel
由Lambda在Up()中创建的c => c.String(nullable: false, annotations: ...)
。
在Generate()方法中,您可以AnnotationValues
通过的Annotations
属性访问自定义ColumnModel
。
要生成添加约束的DDL,您需要生成SQL并调用Statement()方法。例如:
internal class CustomSqlServerMigrationSqlGenerator : SqlServerMigrationSqlGenerator
{
protected override void Generate(AddColumnOperation addColumnOperation)
{
base.Generate(addColumnOperation);
var column = addColumnOperation.Column;
if (column.Type == System.Data.Entity.Core.Metadata.Edm.PrimitiveTypeKind.String)
{
var annotations = column.Annotations;
AnnotationValues minLengthValues;
if (annotations.TryGetValue("minLength", out minLengthValues))
{
var minLength = Convert.ToInt32(minLengthValues.NewValue);
if (minLength > 0)
{
if (Convert.ToString(column.DefaultValue).Trim().Length < minLength)
{
throw new ArgumentException(String.Format("minLength {0} specified for {1}.{2}, but the default value, '{3}', does not satisfy this requirement.", minLength, addColumnOperation.Table, column.Name, column.DefaultValue));
}
using (var writer = new StringWriter())
{
writer.Write("ALTER TABLE ");
writer.Write(Name(addColumnOperation.Table));
writer.Write(" ADD CONSTRAINT ");
writer.Write(Quote("ML_" + addColumnOperation.Table + "_" + column.Name));
writer.Write(" CHECK (LEN(LTRIM(RTRIM({0}))) > {1})", Quote(column.Name), minLength);
Statement(writer.ToString());
}
}
}
}
}
}
如果运行Update-Database -Verbose
,将看到由生成的异常CustomSqlServerMigrationSqlGenerator
:
为dbo.MyEntity.Name指定的minLength 5,但默认值''不满足此要求。
要解决此问题,请在Up()方法中指定一个比最小长度长的defaultValue(例如"unknown"
):
public override void Up()
{
AddColumn("dbo.MyEntity", "Name", c => c.String(nullable: false, defaultValue: "unknown",
annotations: new Dictionary<string, AnnotationValues>
{
{
"minLength",
new AnnotationValues(oldValue: null, newValue: "5")
},
}));
}
现在,如果您重新运行Update-Database -Verbose
,您将看到ALTER TABLE
添加列的ALTER TABLE
语句和添加约束的语句:
ALTER TABLE [dbo]。[MyEntity] ADD [Name] [nvarchar](max)NOT NULL默认'未知' ALTER TABLE [dbo]。[MyEntity] ADD CONSTRAINT [ML_dbo.MyEntity_Name] CHECK(LEN(LTRIM(RTRIM([名称])))> 5)
另请参阅:EF6:编写自己的代码优先迁移操作,它显示了如何实现自定义迁移操作。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句