我的目标是创建自定义Attribute
并允许。 Add-Migration
可以根据它生成自定义代码。
模型和Attribute
类
public class MyAttribute: Attribute {}
public class MyModel
{
public int Id { get; set; }
[MyAttribute]
public string Name { get; set; }
}
MigrationProvider
和AnnotationProvider
:
internal class MyMigrationsAnnotationProvider : SqliteMigrationsAnnotationProvider
{
public override IEnumerable<IAnnotation> For( IProperty property )
{
MemberInfo MInfo = property.PropertyInfo ?? ( MemberInfo ) property.FieldInfo;
MyAttribute MyAttr = MInfo?.GetCustomAttribute<MyAttribute>();
if ( MyAttr != null )
{
return base.For( property ).Concat( new IAnnotation[] { new Annotation( "MyAttribute", true ) } );
}
return base.For( property );
}
}
internal class MyMigrationsSqlGenerator : SqliteMigrationsSqlGenerator
{
public MyMigrationsSqlGenerator( IRelationalCommandBuilderFactory IRFactory, ISqlGenerationHelper ISHelper, IRelationalTypeMapper Mapper, IRelationalAnnotationProvider AnProvider )
: base( IRFactory, ISHelper, Mapper, AnProvider ) {}
protected override void Generate( AddColumnOperation operation, IModel model, MigrationCommandListBuilder builder )
{
throw new Exception( "Hello world" );
// Here's where I got it wrong.
// I thought I should be able to read the "MyAttribute" annotation from here and generate extra code in the Up method
/*
if( operation.FindAnnotation( "MyAttribute" ) != null )
{
builder.AppendLine( "Hello there, not sure if this would work." );
}
*/
}
}
class MyContext : DbContext
{
public DbSet<MyModel> MModel { get; set; }
protected override void OnConfiguring( DbContextOptionsBuilder optionsBuilder )
{
optionsBuilder.UseSqlite( "Data Source=mydata.db" );
optionsBuilder.ReplaceService<IMigrationsSqlGenerator, MyMigrationsSqlGenerator>();
optionsBuilder.ReplaceService<IMigrationsAnnotationProvider, MyMigrationsAnnotationProvider>();
}
}
生成的迁移代码(有些清理)
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "MyModel",
columns: table => new
{
Id = table.Column<string>(nullable: false),
Name = table.Column<string>(nullable: false)
.Annotation("MyAttribute", true),
});
// The following line is what I want it to be generated
migrationBuilder.Sql( "I WANT MY CUSTOM QUERY BE GENERATED HERE" );
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable( name: "MyModel" );
// The following line is what I want it to be generated
migrationBuilder.Sql( "I WANT MY CUSTOM QUERY BE GENERATED HERE" );
}
如您所见,MyAttribute
注释已成功添加到Up
方法中。但是,我似乎无法覆盖Generate
方法,因为在运行Hello world
时没有Add-Migration
异常抛出。
我正在使用EF Core 1.1.5
提前致谢!
答案 0 :(得分:0)
问题在于,只有在将新列添加到现有表时才调用const stringArray = [`${template}`] as any;
stringArray.raw = [`${template}`];
return html(stringArray as TemplateStringsArray);
方法。
对于AddColumnOperation
,您需要替代CreateTable
方法。 void Generate(CreateTableOperation operation, IModel model, MigrationCommandListBuilder builder)
包含相同CreateTableOperation
类型的Operations属性。
这是一个完整的例子
AddColumnOperation
希望这会有所帮助!
答案 1 :(得分:0)
---------------
dt = 2018-09-14T02:33:00.000Z
formatted dt = Sep 13, 2018
---------------
newdt = Thu Sep 13 2018 19:33:00 GMT-0700 (Pacific Daylight Time)
formatted newdt = Sep 13, 2018
---------------
new date = Fri, 14 Sep 2018 02:33:00 GMT
formatted new date = Sep 13, 2018 <-- TRYING TO GE THIS TO SHOW Sep 14th
仅可处理已生成的IMigrationsSqlGenerator
。要检测新MigrationOperation
中的更改,您可能需要替换Attribute
服务。然后,您可以返回一个新的SqlOperation(或自定义类型),以及两个模型之间的其他区别。
从正面看,这意味着您也可以在Down进程中生成撤消操作。