Entity framework 使用Entity Framework 6,自定义代码优先迁移&;CSharpMigrationCodeGenerator

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

我最近开始使用EntityFramework6的代码优先自定义迁移。它工作得很好,但我想做的一件事是在尝试重命名索引时生成一对
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-SQL
DROP
/
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()代码中的匿名参数添加,它将获得该信息,但有人可能会争辩