Подтвердить что ты не робот

Как я могу остановить миграции Entity Framework 5, добавив dbo. на ключевые имена?

Я начал проект с использованием Entity Framework 4.3 Code First с ручными миграциями и SQL Express 2008 и недавно был обновлен до EF5 (в VS 2010) и заметил, что теперь, когда я меняю что-то вроде ограничения внешнего ключа, код миграции добавляет "ДБО". к началу имени таблицы, и, следовательно, имя внешнего ключа, которое оно создает, неверно для существующих ограничений (и в общем теперь кажется странно названным).

Исходная миграция script в EF 4.3 (примечание ForeignKey ( "Продукты", t = > t.Product_Id)):

    CreateTable(
        "Products",
        c => new
            {
                Id = c.Int(nullable: false, identity: true),
                ProductName = c.String(),
            })
        .PrimaryKey(t => t.Id);

    CreateTable(
        "KitComponents",
        c => new
            {
                Id = c.Int(nullable: false, identity: true),
                Component_Id = c.Int(),
                Product_Id = c.Int(),
            })
        .PrimaryKey(t => t.Id)
        .ForeignKey("Products", t => t.Component_Id)
        .ForeignKey("Products", t => t.Product_Id)
        .Index(t => t.Component_Id)
        .Index(t => t.Product_Id);

Созданы имена внешних ключей: FK_KitComponents_Products_Product_Id FK_KitComponents_Products_Component_Id

Если я затем обновляюсь до EF5 и меняю внешний ключ, код перехода выглядит примерно так (обратите внимание на "dbo.KitComponents" и "dbo.Products" , а не только на "KitComponents" и "Продукты" ):

DropForeignKey("dbo.KitComponents", "Product_Id", "dbo.Products");
DropIndex("dbo.KitComponents", new[] { "Product_Id" });

и сбой обновления базы данных обновлений: ' FK_dbo.KitComponents_dbo.Products_Product_Id' не является ограничением. Не удалось отказаться от ограничения. См. Предыдущие ошибки.

так что, как и в EF5, ограничение имен было изменено с FK_KitComponents_Products_Product_Id в FK_dbo.KitComponents_dbo.Products_Product_Id (с префиксом dbo.)

Как я могу заставить EF5 вести себя так, как это было в EF 4.3, поэтому мне не нужно изменять каждый фрагмент нового кода миграции, который он выплевывает?

Я не смог найти никаких заметок о том, почему это изменилось и что с ним делать: (

4b9b3361

Ответ 1

Вы можете настроить сгенерированный код путем подклассификации класса CSharpMigrationCodeGenerator:

class MyCodeGenerator : CSharpMigrationCodeGenerator
{
    protected override void Generate(
        DropIndexOperation dropIndexOperation, IndentedTextWriter writer)
    {
        dropIndexOperation.Table = StripDbo(dropIndexOperation.Table);

        base.Generate(dropIndexOperation, writer);
    }

    // TODO: Override other Generate overloads that involve table names

    private string StripDbo(string table)
    {
        if (table.StartsWith("dbo."))
        {
            return table.Substring(4);
        }

        return table;
    }
}

Затем установите его в свой класс конфигурации миграции:

class Configuration : DbMigrationsConfiguration<MyContext>
{
    public Configuration()
    {
        CodeGenerator = new MyCodeGenerator();
    }
}

Ответ 2

Для автоматического переноса используйте этот код:

public class MyOwnMySqlMigrationSqlGenerator : MySqlMigrationSqlGenerator
{
    protected override MigrationStatement Generate(AddForeignKeyOperation addForeignKeyOperation)
    {
        addForeignKeyOperation.PrincipalTable = addForeignKeyOperation.PrincipalTable.Replace("dbo.", "");
        addForeignKeyOperation.DependentTable = addForeignKeyOperation.DependentTable.Replace("dbo.", "");
        MigrationStatement ms = base.Generate(addForeignKeyOperation);
        return ms;
    }
}

И установите его в конфигурации:

SetSqlGenerator("MySql.Data.MySqlClient", new MyOwnMySqlMigrationSqlGenerator());

Ответ 3

Это прекрасный ответ, однако, если вы просто ищете подход "быстрого исправления", там это также EF Migrations DropForeignKey терпит неудачу, когда ключ находится в базовом классе

Использовать перегрузку DropForeignKey, которая содержит параметры mainName и имя - что в данном случае означает имя ограничения!

Ответ 4

Улучшая ответ на bricelam, я пробовал это на EF6. Сделано несколько изменений, чтобы сохранить схему как часть имени таблицы и удалить ее только из имени FK или PK

internal class MyCodeGenerator : CSharpMigrationCodeGenerator
{
    protected override void Generate(AddForeignKeyOperation addForeignKeyOperation, IndentedTextWriter writer)
    {
        addForeignKeyOperation.Name = this.StripDbo(addForeignKeyOperation.Name, addForeignKeyOperation.DependentTable);
        addForeignKeyOperation.Name = this.StripDbo(addForeignKeyOperation.Name, addForeignKeyOperation.PrincipalTable);
        base.Generate(addForeignKeyOperation, writer);
    }

    protected override void Generate(AddPrimaryKeyOperation addPrimaryKeyOperation, IndentedTextWriter writer)
    {
        addPrimaryKeyOperation.Name = StripDbo(addPrimaryKeyOperation.Name, addPrimaryKeyOperation.Table);
        base.Generate(addPrimaryKeyOperation, writer);
    }

    protected override void Generate(DropForeignKeyOperation dropForeignKeyOperation, IndentedTextWriter writer)
    {
        dropForeignKeyOperation.Name = this.StripDbo(dropForeignKeyOperation.Name, dropForeignKeyOperation.DependentTable);
        dropForeignKeyOperation.Name = this.StripDbo(dropForeignKeyOperation.Name, dropForeignKeyOperation.PrincipalTable);
        base.Generate(dropForeignKeyOperation, writer);
    }

    protected override void Generate(DropPrimaryKeyOperation dropPrimaryKeyOperation, IndentedTextWriter writer)
    {
        dropPrimaryKeyOperation.Name = StripDbo(dropPrimaryKeyOperation.Name, dropPrimaryKeyOperation.Table);
        base.Generate(dropPrimaryKeyOperation, writer);
    }

    private string StripDbo(string objectName, string tableName)
    {
        if (tableName.StartsWith("dbo."))
        {
            return objectName.Replace(tableName, tableName.Substring(4));
        }

        return objectName;
    }
}