1

I have an entity framework code first object with a self referencing key. The child records don't have the parent id in the self referencing key when the data is written to the database.

public class Contract
{
    public Contract()
    {
        Contracts = new List<Contract>();
    }


    public int Id { get; set; }
    public List<Contract> Contracts { get; set; }

}

The object has many more properties than above but I've simplified for the sake of example. This is not a many to many relationship. Each contract has only one parent, apart from master contracts that have no parents.

When I add a sub contract to the list of contracts and I call SaveChanges on the DBContext, the contract and sub contract are written to the database with all fields correct. Apart from the entity framework generated field Contract_Id which is null.

I've got similar self referencing keys working correctly with other classes, in fact the contract has these classes as properties. These other classes all work as expected, with the self referencing keys indicating the parent object all populated correctly.

I've created a very simple test class the same as above just with Test prepended to the class name and that works correctly. I've created a simple test with my Contract class and that does not work correctly.

What I'd like to be able to do is debug the entity framework SaveChanges method but I'm not sure that's possible.

Does anybody have any idea what to look for in terms of what I've done wrong or how to debug this?

Giles Roberts
  • 6,407
  • 6
  • 48
  • 63

2 Answers2

1

You have to modify your entity like that:

public class Contract
{
  public Contract()
  {
    this.Contracts  = new List<Contract>();
  }
  public int Id { get; set; }

  public int? ContractParentId
  {
    get; set; 
  }

  public Contract ContractParent { get; set; }
  public List<Contract> Contracts { get; set; }
}

And use it like that:

using (var dbContext = new MyDatabaseContext(productionConnectionString))
{
  // You need this for fixup
  var contract1 = dbContext.Contracts.Create<Contract>();
  var contract2 = dbContext.Contracts.Create<Contract>();

  dbContext.Contracts.Add(contract1);
  dbContext.Contracts.Add(contract2);

  contract1.Contracts.Add(contract2);

  dbContext.SaveChanges();
}

You have to modify also your DbContext, because it is not possible to define this type of relation in Code first you need Fluent API:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  modelBuilder.Entity<Contract>().HasOptional(c => c.ContractParent).WithMany(c => c.Contracts).HasForeignKey(c => c.ContractParentId);
  base.OnModelCreating(modelBuilder);
}
Bassam Alugili
  • 16,345
  • 7
  • 52
  • 70
  • I've marked your answer as correct because it was the order that I was adding the sub contracts to the database context that was causing the issue. – Giles Roberts Jun 29 '16 at 16:29
  • 1
    I turns out that if you add the sub contracts to the master contract after you've added the master contract to the context, the self referencing keys don't get populated when you SaveChanges. All other fields in the subcontract get populated correctly. I didn't have to add the additional line of code in OnModelCreating to get this to work. – Giles Roberts Jun 29 '16 at 16:34
0

Try this:

Your model:

public class Contract
{
    public Contract()
    {
        Contracts = new List<Contract>();
    }


    public int Id { get; set; }
    public virtual IList<Contract> Contracts { get; set; }
}

use fluent API, on your DBContext try this:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Contract>().HasMany(m => m.Contracts).WithMany();
}
jomsk1e
  • 3,585
  • 7
  • 34
  • 59
  • `virtual` is the key keyword here! – Uwe Keim Jun 29 '16 at 12:26
  • Thanks. I tried that and entity framework created a link table with a Contract_Id and Contract_Id1 and removed the Contract_Id from the Contracts table. I ran the test and the Contracts records were created but nothing was in the link table after I ran my contract creation test. – Giles Roberts Jun 29 '16 at 12:49
  • BTW this isn't a many to many relationship. Each child has just the one parent. – Giles Roberts Jun 29 '16 at 12:52