Question

Using Entity Framework Code First, I'm seeing very strange behavior when inserting a row with a composite key. The composite key consists of a guid ID field and a guid foreign key field, creating an "identifying relationship". The strange behavior is that regardless of what I set the ID and foreign key field to, the generated SQL sets them both to the foreign key value.

My classes look like this:

public class Parent {
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public Guid Id { get; set; }
    public ICollection<Child> Children { get; set; }
}

public class Child {
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public Guid Id { get; set; }
    public Guid ParentId { get; set; }
}

In my DbContext file I have:

modelBuilder.Entity<Child>().HasKey(c => new { c.Id, c.ParentId });

Doing something like:

var parent = new Parent() { Id = Guid.NewGuid() };
var child = new Child() { Id = Guid.NewGuid(), ParentId = parent.Id };
parent.Children.Add(child);

You'd think the SQL executed would insert a new child with differing Id and ParentId values. But instead, what I'm seeing is:

// Assume parent is already in the DB, with ID of '1b1a6ecd-00ad-4265-ac0d-9a50bd30e247'
INSERT [dbo].[Child]
   ([Id],
    [ParentId])
VALUES ('1b1a6ecd-00ad-4265-ac0d-9a50bd30e247' /* @0 */,
    '1b1a6ecd-00ad-4265-ac0d-9a50bd30e247' /* @1 */)

Why is the SQL using the ParentId value for both fields? This doesn't make sense at all.

UPDATE

Unless I totally misunderstand something fundamental to EF, I think this must be a bug. I've uploaded a tiny reproducible project to http://1drv.ms/1kX2oVC

It uses EF 6.1 and .NET 4.5. I'm hoping some EF expert can chime in here and confirm this is a bug, or that I'm doing something fundamentally wrong.

Was it helpful?

Solution

With this set up Entity Framework isn't able to properly infer the associations. You have two options how to fix it:

  • Add modelBuilder.Entity<Parent>().HasMany(x => x.Children).WithRequired().HasForeignKey(x => x.ParentId); into your OnModelCreating.

or

  • Add public Parent Parent { get; set; } into your Child entity.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top