I have four entities defined using EF6 Code First:
public class Item1
{
[Key]
[StringLength(50)]
public string Name { get; set; }
}
public partial class Item2
{
[Key]
[Column(Order = 0)]
[StringLength(50)]
public string Item1Name { get; set; }
[Key]
[Column(Order = 1)]
[StringLength(50)]
public string Name { get; set; }
}
public partial class Item3
{
[Key]
[Column(Order = 0)]
[StringLength(50)]
public string Item1Name { get; set; }
[Key]
[Column(Order = 1)]
[StringLength(50)]
public string Item2Name{ get; set; }
[Key]
[Column(Order = 2)]
[StringLength(50)]
public string Name { get; set; }
}
public partial class Item4
{
[Key]
[Column(Order = 0)]
[StringLength(50)]
public string Item1Name { get; set; }
[Key]
[Column(Order = 1)]
[StringLength(50)]
public string Item2Name{ get; set; }
[Key]
[Column(Order = 2)]
[StringLength(50)]
public string Item3Name{ get; set; }
[Key]
[Column(Order = 3)]
[StringLength(50)]
public string Name{ get; set; }
}
(I omitted the navigation properties, but they are there.)
With the relationships defined like this:
modelBuilder.Entity<Item1>()
.HasMany(e => e.Item2s)
.WithRequired(e => e.Item1)
.HasForeignKey(e => new { e.Item1Name})
.WillCascadeOnDelete(false);
modelBuilder.Entity<Item2>()
.HasMany(e => e.Item3s)
.WithRequired(e => e.Item2)
.HasForeignKey(e => new { e.Item1Name, e.Item2Name })
.WillCascadeOnDelete(false);
modelBuilder.Entity<Item3>()
.HasMany(e => e.Item4s)
.WithRequired(e => e.Item3)
.HasForeignKey(e => new { e.Item1Name, e.Item2Name, e.Name})
.WillCascadeOnDelete(false);
Now when I try to insert an Item3 into existingItem2.Item3s like this:
Item3 newItem3 = new Item3();
newItem3.Item4s.Add(new Item4());
existingItem2.Item3s.Add(newItem3);
db.SaveChanges();
I get the following error:
Cannot insert the value NULL into column 'Item1Name', table 'Database.dbo.Item4s'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated.
The weird thing is, after I insert one Item3 into existingItem2.Item3s without the nested Item4, I can insert the nested items using above procedure without any errors. I've tried explicitly designating all the keys with [DatabaseGenerated(DatabaseGeneratedOption.None)]
, but it makes no difference. What could be at play here?
Edit
I narrowed down the bug and why it sometimes happens and sometimes not. In my program, in addition to what I described, I was also setting existingItem2.someUnrelatedNonKeyIntegerValue = someValue;
. Turns out, that if that would actually change the value (it got set always) EF would generate a failing query. Seems to be a bug in EF, right? I worked around it like this:
if (existingItem2.someUnrelatedNonKeyIntegerValue != someValue)
{
existingItem2.someUnrelatedNonKeyIntegerValue = someValue;
db.SaveChanges();
}
Item3 newItem3 = new Item3();
newItem3.Item4s.Add(new Item4());
existingItem2.Item3s.Add(newItem3);
db.SaveChanges();
(By the way, the integer doesn't contain ID in the name, and really isn't marked as a key in the database.)