我的数据库具有这样的实体Driver
和DriverWork
:
已编辑:
public class Driver
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class DriverWork
{
[Key]
public int Id { get; set; }
public string FromLocation { get; set; }
public string ToLocation { get; set; }
public int Price { get; set; }
public DateTime Date { get; set; }
public int DriverId { get; set; }
[ForeignKey(nameof(DriverId))]
public Driver Driver { get; set; }
}
,并且在那些实体中包含许多行。现在,我添加了另一个名称为WorkPage
的实体,它从此更改了关系:
DriverWork --> Driver
对此:
DriverWork --> WorkPage --> Driver
更改后的模型(Driver
仍然是旧模型):
public class Driver
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class WorkPage
{
[Key]
public int Id { get; set; }
public byte CommissionPercentage { get; set; }
public bool IsClosed { get; set; }
public DateTime? DateClosed { get; set; }
public int DriverId { get; set; }
[ForeignKey(nameof(DriverId))]
public Driver Driver { get; set; }
}
public class DriverWork
{
[Key]
public int Id { get; set; }
public string FromLocation { get; set; }
public string ToLocation { get; set; }
public int Price { get; set; }
public DateTime Date { get; set; }
public int WorkPageId { get; set; }
[ForeignKey(nameof(WorkPageId))]
public WorkPage WorkPage { get; set; }
}
添加新的迁移后,我知道我应该在Up
方法中进行更改,因为某些驱动程序当前没有任何WorkPage
,我应该至少添加一个{{1} },因此,当前WorkPage
项也必须将其DriverWork
的值更改为与该DriverId
关联的有效WorkPageId
。但是我不知道该如何在EF6中进行迁移?
在不更改Driver
方法的情况下,EF在运行Up
命令后给出此错误:
update-database
有帮助吗?
答案 0 :(得分:4)
正弦这是一个艰难的转变,我建议进行两次通过。
首先,将DriverId
FK保留在DriverWork
中,并使DriverId
中的WorkPage
可选(可为空):
public class WorkPage
{
[Key]
public int Id { get; set; }
public byte CommissionPercentage { get; set; }
public bool IsClosed { get; set; }
public DateTime? DateClosed { get; set; }
public int? DriverId { get; set; }
[ForeignKey(nameof(DriverId))]
public Driver Driver { get; set; }
}
public class DriverWork
{
[Key]
public int Id { get; set; }
public string FromLocation { get; set; }
public string ToLocation { get; set; }
public int Price { get; set; }
public DateTime Date { get; set; }
public int DriverId { get; set; }
[ForeignKey(nameof(DriverId))]
public Driver Driver { get; set; }
public int WorkPageId { get; set; }
[ForeignKey(nameof(WorkPageId))]
public WorkPage WorkPage { get; set; }
}
生成新的迁移。应该是这样的:
public override void Up()
{
CreateTable(
"dbo.WorkPage",
c => new
{
Id = c.Int(nullable: false, identity: true),
CommissionPercentage = c.Byte(nullable: false),
IsClosed = c.Boolean(nullable: false),
DateClosed = c.DateTime(),
DriverId = c.Int(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Driver", t => t.DriverId, cascadeDelete: true)
.Index(t => t.DriverId);
AddColumn("dbo.DriverWork", "WorkPageId", c => c.Int());
CreateIndex("dbo.DriverWork", "WorkPageId");
AddForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPage", "Id");
}
执行迁移。然后,通过从Driver
中删除DriverWork
并将DriverId
中的WorkPage
设为必需(非null)来恢复所需的实体模型:
public class WorkPage
{
[Key]
public int Id { get; set; }
public byte CommissionPercentage { get; set; }
public bool IsClosed { get; set; }
public DateTime? DateClosed { get; set; }
public int DriverId { get; set; }
[ForeignKey(nameof(DriverId))]
public Driver Driver { get; set; }
}
public class DriverWork
{
[Key]
public int Id { get; set; }
public string FromLocation { get; set; }
public string ToLocation { get; set; }
public int Price { get; set; }
public DateTime Date { get; set; }
public int WorkPageId { get; set; }
[ForeignKey(nameof(WorkPageId))]
public WorkPage WorkPage { get; set; }
}
生成第二个新迁移。它应该看起来像这样:
public override void Up()
{
DropForeignKey("dbo.DriverWork", "DriverId", "dbo.Driver");
DropForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPages");
DropIndex("dbo.DriverWork", new[] { "DriverId" });
DropIndex("dbo.DriverWork", new[] { "WorkPageId" });
AlterColumn("dbo.DriverWork", "WorkPageId", c => c.Int(nullable: false));
CreateIndex("dbo.DriverWork", "WorkPageId");
AddForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPage", "Id", cascadeDelete: true);
DropColumn("dbo.DriverWork", "DriverId");
}
使用Sql
方法填充WorkPage
表数据并在需要之前更新WorkTableId
FK。例如,将以下内容插入Up
方法的开头:
Sql(@"insert into dbo.WorkPage (CommissionPercentage, IsClosed, DateClosed, DriverId) select 0, 0, null, DriverId from dbo.DriverWork");
Sql(@"update dbo.DriverWork set WorkPageId = WP.Id from dbo.DriverWork DW join dbo.WorkPage WP on DW.DriverId = WP.DriverId");
执行迁移即可完成。
实际上,转换数据的Sql
调用可以在第一个迁移Up
方法的结尾。
事先了解了所有这些信息,您可以按原样保留新模型(跳过第一步),只需将生成的迁移Up
方法替换为以上两者的并集即可,例如
public override void Up()
{
CreateTable(
"dbo.WorkPage",
c => new
{
Id = c.Int(nullable: false, identity: true),
CommissionPercentage = c.Byte(nullable: false),
IsClosed = c.Boolean(nullable: false),
DateClosed = c.DateTime(),
DriverId = c.Int(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Driver", t => t.DriverId, cascadeDelete: true)
.Index(t => t.DriverId);
AddColumn("dbo.DriverWork", "WorkPageId", c => c.Int());
CreateIndex("dbo.DriverWork", "WorkPageId");
AddForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPage", "Id");
Sql(@"insert into dbo.WorkPage (CommissionPercentage, IsClosed, DateClosed, DriverId) select 0, 0, null, DriverId from dbo.DriverWork");
Sql(@"update dbo.DriverWork set WorkPageId = WP.Id from dbo.DriverWork DW join dbo.WorkPage WP on DW.DriverId = WP.DriverId");
DropForeignKey("dbo.DriverWork", "DriverId", "dbo.Driver");
DropForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPages");
DropIndex("dbo.DriverWork", new[] { "DriverId" });
DropIndex("dbo.DriverWork", new[] { "WorkPageId" });
AlterColumn("dbo.DriverWork", "WorkPageId", c => c.Int(nullable: false));
CreateIndex("dbo.DriverWork", "WorkPageId");
AddForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPage", "Id", cascadeDelete: true);
DropColumn("dbo.DriverWork", "DriverId");
}