Entity framework 如何停止Entity Framework 5迁移添加dbo。输入关键名称?

Entity framework 如何停止Entity Framework 5迁移添加dbo。输入关键名称?,entity-framework,entity-framework-5,Entity Framework,Entity Framework 5,我使用Entity Framework 4.3代码启动了一个项目,首先是手动迁移和SQL Express 2008,最近更新为EF5(在VS 2010中),注意到现在当我更改外键约束之类的内容时,迁移代码添加了“dbo”表名的开头以及它构造的外键名对于现有约束来说是不正确的(通常现在看起来命名很奇怪) EF4.3中的原始迁移脚本(注意ForeignKey(“产品”,t=>t.Product\u Id)): CreateTable( “产品”, c=>新的 { Id=c.Int(可为空:fals

我使用Entity Framework 4.3代码启动了一个项目,首先是手动迁移和SQL Express 2008,最近更新为EF5(在VS 2010中),注意到现在当我更改外键约束之类的内容时,迁移代码添加了“dbo”表名的开头以及它构造的外键名对于现有约束来说是不正确的(通常现在看起来命名很奇怪)

EF4.3中的原始迁移脚本(注意ForeignKey(“产品”,t=>t.Product\u Id)):

CreateTable(
“产品”,
c=>新的
{
Id=c.Int(可为空:false,标识:true),
ProductName=c.String(),
})
.PrimaryKey(t=>t.Id);
创建表(
“风筝组件”,
c=>新的
{
Id=c.Int(可为空:false,标识:true),
组件Id=c.Int(),
Product_Id=c.Int(),
})
.PrimaryKey(t=>t.Id)
.ForeignKey(“产品”,t=>t.Component_Id)
.ForeignKey(“产品”,t=>t.Product\u Id)
.Index(t=>t.Component\u Id)
.Index(t=>t.Product_Id);
生成的外键名称: FK\U KIT组件\U产品\U产品\U Id FK\U KIT组件\U产品\U组件\U Id

如果我随后升级到EF5并更改外键,迁移代码看起来类似于(请注意“dbo.KitComponents”和“dbo.Products”,而不仅仅是“KitComponents”和“Products”):

DropForeignKey(“dbo.KitComponents”、“Product_Id”、“dbo.Products”);
DropIndex(“dbo.KitComponents”,新[]{“Product_Id”});
更新数据库失败,并显示以下消息: “FK_dbo.KitComponents_dbo.Products_Product_Id”不是约束条件。 无法删除约束。请参阅前面的错误

因此,从EF5开始,约束命名似乎已从 FK\U KIT组件\U产品\U产品\U Id 到 FK_dbo.KitComponents_dbo.Products_Product_Id(带dbo.prefix)

我怎样才能让EF5像在EF4.3中那样运行,这样我就不必修改它吐出的每一段新迁移代码


我找不到任何关于此更改原因以及如何处理的发行说明:(

您可以通过对类进行子分类来自定义生成的代码:

然后在迁移配置类中设置它:

class Configuration : DbMigrationsConfiguration<MyContext>
{
    public Configuration()
    {
        CodeGenerator = new MyCodeGenerator();
    }
}
类配置:dbmigrionsconfiguration
{
公共配置()
{
CodeGenerator=新的MyCodeGenerator();
}
}

这是一个很好的答案,但是,如果您只是在寻找一种“快速修复”方法,那么也有这种方法

使用DropForeignKey重载,它包含参数principalName和name——在本例中,这意味着约束名称


对于自动迁移,请使用以下代码:

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());

为了改进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;
    }
}

在EF5中,我们停止剥离dbo,因为如果用户的默认模式不是“dbo”事情会破裂的。现在我们对待dbo就像对待任何其他模式一样。非常感谢@Brice,这正是我所寻找的。我理解这一变化,但认为EF5可能会更优雅地处理现有设置……或者至少给出一个警告。对于阅读和想要EF4行为的其他人,您必须覆盖大多数其他Generate()函数以剥离dbo。并调整StripDbo()函数以返回字符串-因为ref参数对属性无效。@mips,我已相应地更新了代码;我希望在您读取ref参数之前可以更改它。;)我收到错误1'NiDS.Web.Migrations.MigrationsGenerator.Generate(System.Data.Entity.Migrations.Model.DropIndexOperation,System.CodeDom.Compiler.IndentedTextWriter)“:找不到合适的方法覆盖c:\users\wayne blackmon\documents\visual studio 2012\Projects\NiDS 2.0\NiDS.Web\Migrations\MigrationsGenerator.cs 9 33 NiDS.WebWayne,请尝试将IndentedTextWriter更改为System.Data.Entity.Migrations.Utilities.IndentedTextWriter?@Brice Hi Brice,这是否仅适用于使用自己的Up-met自定义迁移hod?我遇到了一个类似的问题,我在你的答案中尝试了类似的方法,但没有效果…为了帮助其他人留下我的评论,这个答案删除了.dbo。当我在console软件包管理器中运行更新数据库时,我还以与AddForeignKeyOperation相同的方式使用了DropForeignKeyOperation,这两个操作非常好,谢谢你的回答。
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;
    }
}