¿Cómo puedo detener las migraciones de Entity Framework 5 añadiendo dbo? ¿en nombres clave?


Comencé un proyecto usando el Código Entity Framework 4.3 Primero con migraciones manuales y SQL Express 2008 y recientemente actualizado a EF5 (en VS 2010) y noté que ahora cuando cambio algo como una restricción de clave foránea, el código de migraciones agrega el "dbo."al principio del nombre de la tabla y por lo tanto el nombre de la clave foránea que construye es incorrecto para las restricciones existentes (y en general ahora parecen tener un nombre extraño).

Script de migración original en EF 4.3 (nota ForeignKey ("Productos", 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);

Nombres de clave foránea generados: FK_KitComponents_Products_Product_Id FK_KitComponents_Products_Component_Id

Si luego actualizo a EF5 y cambio la clave foránea, el código de migración se ve algo como (note el "dbo.KitComponents" y "dbo.Productos " en lugar de solo "KitComponents" y "Productos"):

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

Y la base de datos de actualización falla con el mensaje: "FK_dbo.KitComponents_dbo.Products_Product_Id" no es una restricción. No se pudo soltar la restricción. Ver errores anteriores.

Así que parece que a partir de EF5 el nombre de restricción ha cambiado de FK_KitComponents_Products_Product_Id a FK_dbo.KitComponents_dbo.Products_Product_Id (con dbo. prefijo)

¿Cómo puedo hacer que EF5 se comporte como estaba en EF 4.3 para no tener que alterar cada pieza de código de migración nuevo que escupe?

No he podido encontrar ninguna nota de la versión sobre por qué esto cambió y qué hacer al respecto: (

Author: mips, 2012-08-21

4 answers

Puede personalizar el código generado subclasificando el CSharpMigrationCodeGenerator clase:

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;
    }
}

Luego establézcalo en su clase de configuración de migraciones:

class Configuration : DbMigrationsConfiguration<MyContext>
{
    public Configuration()
    {
        CodeGenerator = new MyCodeGenerator();
    }
}
 29
Author: bricelam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-18 12:38:28

Para Migraciones Automáticas use este código:

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;
    }
}

Y configurarlo en la configuración:

SetSqlGenerator("MySql.Data.MySqlClient", new MyOwnMySqlMigrationSqlGenerator());
 4
Author: Daniloloko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-14 13:53:06

Esta es una buena respuesta, sin embargo, si solo está buscando un enfoque de 'solución rápida', también existe esto EF Migrations DropForeignKey falla cuando key está en una clase base

Use la sobrecarga DropForeignKey que contiene los parámetros principalNAME y name!que en este caso significa constraint name!

 2
Author: Vinney Kelly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:25:39

Mejorando la respuesta de bricelam, probé esto en EF6. Se realizaron algunos cambios para mantener el esquema como parte del nombre de la tabla y solo eliminarlo del nombre FK o 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;
    }
}
 1
Author: Scott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-24 19:50:49