简体   繁体   中英

Entity Framework making wrong property relations

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM