entity-framework – 实体框架6:如何覆盖SQL生成器?
|
副标题[/!--empirenews.page--]
我想在生成数据库模式(DDL)时修改由EF:CF生成的SQL,如 suggested by the Entity Framework team. 如何才能做到这一点? 我无法通过Google找到合适的内容. 解决方法您可以通过调用DbMigrationsConfiguration类的构造函数中的 DbMigrationsConfiguration.SetSqlGenerator()方法,传递数据库提供程序名称(例如,SQL Server的“System.Data.SqlClient”)以及要用于的MigrationSqlGenerator实例来覆盖Entity Framework使用的MigrationSqlGenerator.该数据库提供者.
考虑您链接到的the work item中的示例: public class MyEntity
{
public int Id { get; set; }
[Required]
[MinLength(5)]
public string Name { get; set; }
}
假设已生成MyEntity表,并使用Add-Migration命令添加Name字段. 默认情况下,scaffolded迁移是: 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传达最小长度要求,您可以使用specify an attribute-to-column annotation convention.如该文档页面所述,默认SQL生成器会忽略任何 在DbContext的OnModelCreating()覆盖中,添加以下内容: modelBuilder.Conventions.Add(new AttributeToColumnAnnotationConvention<MinLengthAttribute,Int32>("minLength",(property,attributes) => attributes.Single().Length));
添加之后,您可以通过运行Add-Migration -Force AddMyEntity_Name重新生成scaffolded迁移.现在脚手架迁移是: public partial class AddMyEntity_Name : DbMigration
{
public override void Up()
{
AddColumn("dbo.MyEntity",c => c.String(nullable: false,annotations: new Dictionary<string,AnnotationValues>
{
{
"minLength",new AnnotationValues(oldValue: null,newValue: "5")
},}));
}
public override void Down()
{
DropColumn("dbo.MyEntity",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)方法,但只需调用基本实现. 如果你看一下the documentation of 在Generate()方法中,您可以通过ColumnModel的Annotations属性访问自定义AnnotationValues. 要生成添加约束的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());
}
}
}
}
}
}
(编辑:应用网_阳江站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

