GraphDiff
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
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!
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.
Filed https://entityframework.codeplex.com/workitem/2761 as well.