ASP.Net MVC 迁移:您要删除的访问字段
ASP.Net MVC migration: access field you're deleting
在代码优先迁移期间,是否有任何方法可以访问保证仍然存在于数据库中但可能不再存在于您的模型中的字段?
上下文:我正在尝试从一对多关系(单向引用)切换到多对多关系(映射 table)。当然,我想通过为每个预先存在的参考插入一个条目来保留我的数据。迁移似乎是正确的地方。如果我保证迁移总是 运行 在 之前从模型中删除源字段(大概通过检查版本控制提交),我可以例如在我的迁移中包含以下内容(假设引用模型命名为 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; }
}
更改生成的迁移以执行 sql 语句填充多对多 table 在 列被删除之前。
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");
}
...
}
这有一些免费的优势:
- 该语句在事务内部运行,因此如果出现问题,数据库将保持完整
- 您可以填充您的映射 table w/o 加载旧实体 - 将在大型
Foos
table 中表现良好
在代码优先迁移期间,是否有任何方法可以访问保证仍然存在于数据库中但可能不再存在于您的模型中的字段?
上下文:我正在尝试从一对多关系(单向引用)切换到多对多关系(映射 table)。当然,我想通过为每个预先存在的参考插入一个条目来保留我的数据。迁移似乎是正确的地方。如果我保证迁移总是 运行 在 之前从模型中删除源字段(大概通过检查版本控制提交),我可以例如在我的迁移中包含以下内容(假设引用模型命名为 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; }
}
更改生成的迁移以执行 sql 语句填充多对多 table 在 列被删除之前。
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");
}
...
}
这有一些免费的优势:
- 该语句在事务内部运行,因此如果出现问题,数据库将保持完整
- 您可以填充您的映射 table w/o 加载旧实体 - 将在大型
Foos
table 中表现良好