I think it's something wrong with the model in the example below, but I can't figure out what.
In the example I have a Container class with Items containing sub Items. As soon as I try to create a container with more than one level of Items it looses the relationship with the container and therefore fails due to foreign key constraints.
The exception I get is:
Microsoft.EntityFrameworkCore.DbUpdateException : An error occurred while updating the entries. See the inner exception for details. ---- System.Data.SqlClient.SqlException : The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Items_Containers_ContainerId". The conflict occurred in database "Test", table "dbo.Containers", column 'Id'. The statement has been terminated.
When I look at the SQL that EF Core generates, using SQL Profiler, it tries to insert 0 as id for the Container for all non direct children.
So, creating the Container is not a problem, nor is the first level children, but as soon as I add a second level it looses the relationship with the Container.
public class Test
{
public class Container
{
[Required]
public int Id { get; set; }
public IEnumerable<Item> Items { get; set; }
}
public class Item
{
[Required]
public int Id { get; set; }
[Required]
public int ContainerId { get; set; }
public virtual Container Container { get; set; }
public int? ParentItemId { get; set; }
public virtual Item ParentItem { get; set; }
public IEnumerable<Item> ChildItems { get; set; }
}
public class TestContext : DbContext
{
public virtual DbSet<Container> Containers { get; set; }
public virtual DbSet<Item> Items { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Container>()
.HasMany(c => c.Items)
.WithOne(c => c.Container)
.HasForeignKey(c => c.ContainerId);
modelBuilder.Entity<Item>()
.HasOne(x => x.Container)
.WithMany(x => x.Items)
.HasForeignKey(x => x.ContainerId);
modelBuilder.Entity<Item>()
.HasOne(x => x.ParentItem)
.WithMany(x => x.ChildItems)
.HasForeignKey(x => x.ParentItemId);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlServer(
@"Server=(localdb)\mssqllocaldb;Database=Test;Trusted_Connection=True;ConnectRetryCount=0");
}
public void ContextTest()
{
using (var context = new TestContext())
{
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
var container = new Container();
container.Items = new List<Item>
{
new Item
{
ChildItems = new List<Item>
{
new Item()
}
}
};
context.Containers.Add(container);
context.SaveChanges();
}
}
}