ASP.Net MVC迁移:您正在删除的访问字段

时间:2018-01-19 10:56:27

标签: c# asp.net-mvc asp.net-mvc-4 database-migration ef-migrations

在代码优先迁移期间,是否有任何方法可以访问保证仍存在于数据库中但可能不再存在于模型中的字段?

上下文:我试图从一对多关系(单向引用)切换到多对多关系(映射表)。当然,我想通过为每个预先存在的引用插入一个条目来保留我的数据。迁移似乎是正确的地方。如果我保证迁移始终在之前运行,则从模型中删除源字段(可能是通过签出版本控制提交),我可以例如在我的迁移中包含以下内容(假设引用模型名为Foo,引用的名称为Bar):

Models.MyApplicationContext db = new Models.MyApplicationContext();
foreach(Models.Foo foo in db.Foos)
{
    foo.Bars.Add(foo.Bar);
}

但不幸的是,对其他开发者来说,'计算机以及生产环境中,foo.Bar字段将在运行此迁移时从模型中消失,因此我将需要一种不同的方式来访问此字段(仍在数据库中)。除了编写纯SQL之外,我还有其他选择吗?

编辑1:缩小模型类的最小工作示例:

迁移前:

public class Foo
{
    public int Id { get; set; }
    public Bar Bar { get; set; }
    // or public int? BarId { get; set; }
    // (presumably only relevant for implementation details
    // unrelated to my question which I can figure out myself)
}

public class Bar
{
    public int Id { get; set; }
}

迁移后:

public class Foo
{
    public int Id { get; set; }
    public List<Bar> Bars { get; set; }
}

public class Bar
{
    public int Id { get; set; }
    public List<Foo> Foos { get; set; }
}

1 个答案:

答案 0 :(得分:0)

更改生成的迁移,以执行一个sql语句,在列被删除之前填充多个表

public partial class OneToMany : DbMigration
{
    public override void Up()
    {
        DropForeignKey("dbo.Foos", "Bar_Id", "dbo.Bars");
        DropIndex("dbo.Foos", new[] { "Bar_Id" });
        CreateTable(
            "dbo.FooBars",
            c => new
                {
                    Foo_Id = c.Int(nullable: false),
                    Bar_Id = c.Int(nullable: false),
                })
            .PrimaryKey(t => new { t.Foo_Id, t.Bar_Id })
            .ForeignKey("dbo.Foos", t => t.Foo_Id, cascadeDelete: true)
            .ForeignKey("dbo.Bars", t => t.Bar_Id, cascadeDelete: true)
            .Index(t => t.Foo_Id)
            .Index(t => t.Bar_Id);

        // HERE:
        this.Sql("insert into FooBars select Id, Bar_Id from Foos");

        DropColumn("dbo.Foos", "Bar_Id");
    }
    ...
 }

这有一些免费的优点:

  • 语句在事务内部运行,因此如果出现问题,数据库保持不变
  • 您可以填写您的映射表,无需加载旧实体 - 使用大型Foos表格