我的数据库有如下实体 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 --> 驱动程序
对此:
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
,我至少应该为它们添加一个 WorkPage
,当前的 DriverWork
项也必须将它们的 DriverId
值更改为关联的有效 WorkPageId
使用那个 Driver
。但我不知道我应该如何在 EF6 中进行此迁移?
在 Up
方法中没有做任何更改,EF 在运行 update-database
命令后给出了这个错误:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_dbo.DriverWorks_dbo.WorkPages_WorkPageId". The conflict occurred in database "{dblocation}\KHORSHIDDATA.MDF", table "dbo.WorkPages", column 'Id'.
有什么帮助吗?
最佳答案
因为这是一个艰难的转变,我建议分两次执行。
首先,保留 DriverWork
中的 DriverId
FK,并使 WorkPage
中的 DriverId
可选(可为空):
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");
}
执行迁移。然后通过从 DriverWork
中删除 Driver
并使 WorkPage
中的 DriverId
成为必需的(非空)来恢复所需的实体模型:
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");
}
关于c# - 在 Entity Framework 中更改数据库结构和移动数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52054342/