GraphDiff icon indicating copy to clipboard operation
GraphDiff copied to clipboard

PK-FK, zero/one-one relationships with a nullable key on the primary entity causes an error when creating new objects

Open rwdalpe opened this issue 10 years ago • 2 comments

I'm not at my work machine at the moment, so I can't give the exact details, but here's the idea. I'll provide more concrete details tomorrow.

Say you have a model like this

public class PKFKModel_Primary
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int? Id { get; set; }
    public PKFKModel_Secondary Secondary { get; set; }
}

public class PKFKModel_Secondary
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }
}

And a context configuration like

public IDbSet<PKFKModel_Primary> PKFKModel_Primaries { get; set; }
public IDbSet<PKFKModel_Secondary> PKFKModel_Secondaries { get; set; }
...
modelBuilder.Entity<PKFKModel_Primary>().HasOptional(e => e.Secondary).WithRequired();

And a test such as

var model = new PKFKModel_Primary() 
{ 
    Secondary = new PKFKModel_Secondary()
};

using (var context = new TestDbContext())
{
    var result = context.UpdateGraph<PKFKModel_Primary>(model, mapping => mapping.OwnedEntity(e => e.Secondary));
    context.SaveChanges();
}

Then when SaveChanges is called you will get an error about the Secondary object not being able to have a null ID. Even if you make the Id property of the Secondary object nullable, the same error will be thrown. Having a navigation property on the Secondary object does not make a difference either.

It is fully dependent on the nullability of the Primary object. If the Id property of the Primary object is either

  • non-nullable
  • set to a specific value

Then this error does not occur and the function works as expected.

Tomorrow when I'm back at work I can double check the code examples I've given here and provide more details.

Thank you!

rwdalpe avatar Feb 13 '15 02:02 rwdalpe

Looks like this might actually be an Entity Framework bug/misuse?

With the same model and context setup as in refactorthis/GraphDiff#131 I can reproduce it in vanilla entity framework using the following:

PKFKModelPrimary p2 = new PKFKModelPrimary
{
    Name = "p2"
};

PKFKModelSecondary s2 = new PKFKModelSecondary
{
    Name = "s2"
};

PKFKModelPrimary p2s;
PKFKModelSecondary s2s;

using (TestDbContext context = new TestDbContext())
{
    p2s = context.PKFKModelPrimaries.Add(p2);
    s2s = context.PKFKModelSecondaries.Add(s2);
    p2s.Secondary = s2s;
    context.SaveChanges();
}

This is conceptually equivalent to what GraphDiff is doing when constructing its internal object graph. Whether or not this is an actual bug in EF or just a misuse I'm not sure.

The following version works in vanilla EF:

PKFKModelPrimary p2 = new PKFKModelPrimary
{
    Name = "p2",
    Secondary = new PKFKModelSecondary
    {
        Name = "s2"
    }
};

PKFKModelPrimary p2s;

using (TestDbContext context = new TestDbContext())
{
    p2s = context.PKFKModelPrimaries.Add(p2);
    context.SaveChanges();
}

So the difference appears to be in whether the object graph is complete when Add is called or whether it's made piece by piece.

rwdalpe avatar Jun 12 '15 19:06 rwdalpe

Filed https://entityframework.codeplex.com/workitem/2761 as well.

rwdalpe avatar Jun 12 '15 23:06 rwdalpe