I have a database with a lot of tables created using code-first. 3 of the tables are
public class Machine
{
[Key]
public long ID { get; set; }
...
public virtual MachineTypeApprovalHist MachineTypeApproval { get; set; }
}
public class MachineTypeApprovalHist
{
[Key]
public long ID { get; internal set; }
...
}
public class MachineTypeApproval
{
[Key]
public long ID { get; set; }
...
}
The weird thing is that EF creates a foreign key from Machine
to MachineTypeApproval
(not MachineTypeApprovalHist
as it should!). I found out after long time of debugging by looking in the database table directly to see the relations between the tables. The error I got was
The UPDATE statement conflicted with the FOREIGN KEY constraint "FK_dbo.Machines_dbo.MachineTypeApprovals_MachineTypeApproval_ID". The conflict occurred in database "ATPData", table "dbo.MachineTypeApprovals", column 'ID'. The statement has been terminated.
The error comes because it tries to use a ID from MachineTypeApprovalHist
that is not in MachineTypeApprovals
.
I have tried to rename the property MachineTypeApproval to TypeApproval and making a new migration, but it only renamed the table column and index.
I cannot recreate the database from scratch since I will lose my data, so what can I do to fix this?
public class DatabaseContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder
.Entity<Machine>()
.HasOptional(_ => _.MachineTypeApproval)
.WithMany();
}
}
will generate these SQL statements:
ALTER TABLE [dbo].[Machines] WITH CHECK ADD CONSTRAINT [FK_dbo.Machines_dbo.MachineTypeApprovalHists_MachineTypeApproval_ID] FOREIGN KEY([MachineTypeApproval_ID])
REFERENCES [dbo].[MachineTypeApprovalHists] ([ID])
GO
ALTER TABLE [dbo].[Machines] CHECK CONSTRAINT [FK_dbo.Machines_dbo.MachineTypeApprovalHists_MachineTypeApproval_ID]
GO
I found a way to fix this, though I feel it should be easier.
The way I did it was to add another property to my Machine
class to replace the first one.
public class Machine
{
[Key]
public long ID { get; set; }
...
public virtual MachineTypeApprovalHist MachineTypeApproval { get; set; }
//new property
public virtual MachineTypeApprovalHist TypeApproval {get; set;}
}
then I made a new migration which creates a new columns with foreign key to the correct table.
Now, I couldn't just remove my original property and update the database since I would lose data. So first i removed the original property MachineTypeApproval
from Machine
class, then adding a new migration, adding to that migrations Up method the following on the first line before any other call
Sql("update [dbo].Machines set TypeApproval_ID = MachineTypeApproval_ID ");
In this way the first migration correctly creates the new property, the second migration copies data from the old column to the new, and the second migration removes the old column, and my model and db is now correct.
I just hate that I need two migrations to do this. Also it looks like EF uses the property names BEFORE the property type to determine which table to use, which seems totally crazy to me
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.