[英]Changing structure of database and moving data in Entity Framework
My Database has entities Driver
and DriverWork
like this: 我的数据库具有如下实体: Driver
和DriverWork
:
Edited: 编辑:
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; }
}
And contains many rows in those entities. 并且在那些实体中包含许多行。 Now I've added another Entity with name WorkPage
, which changes relation from this: 现在,我添加了另一个名称为WorkPage
实体,该实体WorkPage
更改了关系:
DriverWork --> Driver
To this: 对此:
DriverWork --> WorkPage --> Driver
Models after the change ( Driver
is still the old one): 更改后的型号( 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; }
}
After adding a new migration, I knew that I should make changes in the Up
method because some drivers currently don't have any WorkPage
s and I should at least add one WorkPage
for them, also current DriverWork
items must change their DriverId
value to a valid WorkPageId
that is associated with that Driver
. 添加新的迁移后,我知道我应该对Up
方法进行更改,因为某些驱动程序当前没有任何WorkPage
并且我至少应该WorkPage
添加一个WorkPage
,而且当前DriverWork
项也必须将其DriverId
值更改为与该Driver
关联的有效WorkPageId
。 But I don't know how should I do this migration in EF6? 但是我不知道该如何在EF6中进行迁移?
Without making any changes in Up
method, EF gives this error after running update-database
command: 在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'.
Any help? 有什么帮助吗?
Sine it's a tough transformation, I would suggest performing it with two passes. 确实,这是一个艰难的转变,我建议进行两次通过。
First, keep the DriverId
FK in the DriverWork
and make DriverId
in WorkPage
optional (nullable): 首先,将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; }
}
Generate new migration. 产生新的迁移。 It should be something like this: 应该是这样的:
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");
}
Execute the migration. 执行迁移。 Then restore the desired entity model by removing the Driver
from DriverWork
and making DriverId
in WorkPage
required (non null): 然后通过从DriverWork
删除Driver
并在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; }
}
Generate a second new migration. 生成第二个新迁移。 It should look something like this: 它看起来应该像这样:
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");
}
Use Sql
methods to populate the WorkPage
table data and update the WorkTableId
FK before making it required. 使用Sql
方法填充WorkPage
表数据并在需要之前更新WorkTableId
FK。 For instance, insert the following at the beginning of the Up
method: 例如,在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");
Execute the migration and you are done. 执行迁移,您就完成了。
Actually the Sql
calls which transform the data can be at the end of the first migration Up
method. 实际上,转换数据的Sql
调用可以在第一个Migration Up
方法的结尾。
Knowing all that in advance, you can keep your new model as is (skip the first step) and simply replace the generated migration Up
method with the union of the above two, eg 事先了解所有这些信息,您可以保持新模型不变(跳过第一步),并用上述两个方法的并集简单地替换生成的migration 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");
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.