Entity framework 使用Entity Framework 6,自定义代码优先迁移&;CSharpMigrationCodeGenerator
我最近开始使用EntityFramework6的代码优先自定义迁移。它工作得很好,但我想做的一件事是在尝试重命名索引时生成一对Entity framework 使用Entity Framework 6,自定义代码优先迁移&;CSharpMigrationCodeGenerator,entity-framework,entity-framework-6,entity-framework-migrations,Entity Framework,Entity Framework 6,Entity Framework Migrations,我最近开始使用EntityFramework6的代码优先自定义迁移。它工作得很好,但我想做的一件事是在尝试重命名索引时生成一对CreateIndex()和DropIndex()语句,而不是像默认的csharpmigationcodegenerator那样使用rename索引() 例如,我目前使用fluent映射中的数据注释重命名索引,如下所示: Property(x => x.TeacherId).HasColumnAnnotation("Index", new IndexAnnotati
CreateIndex()
和DropIndex()
语句,而不是像默认的csharpmigationcodegenerator
那样使用rename索引()
例如,我目前使用fluent映射中的数据注释重命名索引,如下所示:
Property(x => x.TeacherId).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Students_TeacherId")));
这里的问题是,默认情况下,当我添加新迁移以捕获模型的此更改时,EF6希望生成以下代码:
using System;
using System.Data.Entity.Migrations;
namespace MyApp.Migrations
{
public partial class RenameIndexTest : DbMigration
{
public override void Up()
{
// BAD: [RenameIndex] will generate a "EXEC sp_rename" statement.
RenameIndex(table: "dbo.Students", name: "IX_TeacherId", newName: "IX_Students_TeacherId");
}
public override void Down()
{
RenameIndex(table: "dbo.Students", name: "IX_Students_TeacherId", newName: "IX_TeacherId");
}
}
}
但我真正需要EF6生成的是:
using System;
using System.Data.Entity.Migrations;
namespace MyApp.Migrations
{
public partial class RenameIndexTest : DbMigration
{
public override void Up()
{
// GOOD: We generate separate SQL statements to drop & add the index.
DropIndex(table: "dbo.Students", name: "IX_TeacherId");
CreateIndex(table: "dbo.Students", name: "IX_Students_TeacherId", column: "TeacherId");
}
public override void Down()
{
DropIndex(table: "dbo.Students", name: "IX_Students_TeacherId");
CreateIndex(table: "dbo.Students", name: "IX_TeacherId", column: "TeacherId");
}
}
}
我们的数据团队严格要求开发人员在重命名索引时使用T-SQLDROP
/CREATE
语句。到目前为止,我还无法找到一种方法来覆盖RenameIndex()
语句的行为,使用一个自定义类,该类使用csharpmigationcodegenerator
作为基类,因为RenameIndexOperation
类没有关于已创建索引的列的任何信息
这是我自己所能做到的:
namespace MyApp.Migrations
{
internal class CustomCSharpMigrationCodeGenerator : CSharpMigrationCodeGenerator
{
protected override string Generate(IEnumerable<MigrationOperation> operations, string @namespace, string className)
{
var customizedOperations = new List<MigrationOperation>();
foreach (var operation in operations)
{
if (operation is RenameIndexOperation)
{
var renameIndexOperation = operation as RenameIndexOperation;
var dropIndexOperation = new DropIndexOperation(operation.AnonymousArguments)
{
Table = renameIndexOperation.Table,
Name = renameIndexOperation.Name
};
var createIndexOperation = new CreateIndexOperation(operation.AnonymousArguments)
{
Table = renameIndexOperation.Table,
Name = renameIndexOperation.NewName,
// HELP: How do I get this information about the existing index?
// HELP: How do I specify what columns the index should be created on?
IsUnique = false,
IsClustered = false
};
// Do not generate a RenameIndex() statement; instead, generate a pair of DropIndex() and CreateIndex() statements.
customizedOperations.Add(dropIndexOperation);
customizedOperations.Add(createIndexOperation);
}
else
{
customizedOperations.Add(operation);
}
}
return base.Generate(customizedOperations, @namespace, className);
}
}
}
名称空间MyApp.Migrations
{
内部类CustomCSharpMigrationCodeGenerator:CSharpMigrationCodeGenerator
{
受保护的重写字符串生成(IEnumerable操作、string@namespace、string className)
{
var customizedOperations=新列表();
foreach(操作中的var操作)
{
如果(操作为重命名IndexOperation)
{
var renameIndexOperation=作为renameIndexOperation的操作;
var dropIndexOperation=新的dropIndexOperation(operation.AnonymousArguments)
{
Table=重命名IndexOperation.Table,
Name=重命名IndexOperation.Name
};
var createIndexOperation=新的createIndexOperation(operation.AnonymousArguments)
{
Table=重命名IndexOperation.Table,
Name=重命名IndexOperation.NewName,
//帮助:如何获取有关现有索引的信息?
//帮助:如何指定应在哪些列上创建索引?
IsUnique=false,
IsClustered=false
};
//不要生成RenameIndex()语句;而是生成一对DropIndex()和CreateIndex()语句。
添加(dropIndexOperation);
添加(createIndexOperation);
}
其他的
{
自定义操作。添加(操作);
}
}
返回base.Generate(定制操作,@namespace,className);
}
}
}
这有意义吗?更重要的是,是否有人对如何进行有任何建议或想法?不管怎样,先谢谢你 我要结束这个问题。我从来没能做到我想做的事。。。它不是一个破坏交易的工具,我只是希望EF6能够(轻松地)控制正在创建的索引的名称
IIRC,我按照@steve greene的建议,使用
Sql()
方法手动指定了索引的名称。我结束了这个问题。我从来没能做到我想做的事。。。它不是一个破坏交易的工具,我只是希望EF6能够(轻松地)控制正在创建的索引的名称
IIRC,我按照@steve greene的建议做了,并使用
Sql()
方法手动指定了索引的名称。您可以使用自定义的SqlServerMigrationSqlGenerator来接近这一点。请参阅,您可以拦截CreateIndexOperation()并编写自己的SQL。请参见此处,我正在尝试拦截重命名IndexOperation
,而不是CreateIndexOperation
。在添加迁移以正确设置索引之前,该索引已存在。还有,它公开了我需要的Columns属性。但是,这并没有暴露出来。@SteveGreene:对不起,上面的空间不够了。基本上,我需要一种方法将重命名IndexOperation
重写为一对DropIndexOperation
和CreateIndexOperation
操作。简单地拦截我的CreateIndexOperation
是行不通的。@SteveGreene:这正是我在最初的帖子中所说的。。。我的最后一个代码片段甚至说明了我是如何无法做到这一点的。如果您将其作为Up()代码中的匿名参数添加,它将获得该信息,但有人可能会认为您最好使用Sql(“DROP INDEX…”);和Sql(“创建索引…”);您可以使用定制的SqlServerMigrationSqlGenerator接近这一点。请参阅,您可以拦截CreateIndexOperation()并编写自己的SQL。请参见此处,我正在尝试拦截重命名IndexOperation
,而不是CreateIndexOperation
。在添加迁移以正确设置索引之前,该索引已存在。还有,它公开了我需要的Columns属性。但是,这并没有暴露出来。@SteveGreene:对不起,上面的空间不够了。基本上,我需要一种方法将重命名IndexOperation
重写为一对DropIndexOperation
和CreateIndexOperation
操作。简单地拦截我的CreateIndexOperation
是行不通的。@SteveGreene:这正是我在最初的帖子中所说的。。。我的上一个代码片段甚至说明了我是如何无法做到这一点的。如果您将其作为Up()代码中的匿名参数添加,它将获得该信息,但有人可能会争辩