I've a very basic setup to test and understand why EF Core 6 don't save related entities by default when adding new item to the many end of an already saved entity.
- Can someone explain to me what is wrong with this setup?
- And how can I make EF detect changes by default? is there any configuration that I can do in order to make EF detect changes without setting
entry
state manually?
I also followed the sample provided in Microsoft docs and it is giving me the same result (DbUpdateConcurrencyException: The database operation was expected to affect 1 row(s), but actually affected 0 row(s);
)
using Microsoft.EntityFrameworkCore;
var db = new AuthorsDbContext();
db.Database.EnsureCreated();
var author = new Author();
author.Id = Guid.NewGuid();
db.Authors.Add(author);
db.SaveChanges();
// Not working
// var author1 = await db.Authors.FindAsync(new object?[] { author.Id });
// author1.Posts.Add(new Post() { Id = Guid.NewGuid(), Title = "test" });
// db.SaveChanges(); //-> DbUpdateConcurrencyException: The database operation was expected to affect 1 row(s), but actually affected 0 row(s);
// Not working
// var author1 = await db.Authors.Include(a => a.Posts).FirstAsync(a => a.Id == author.Id);
// author1.Posts.Add(new Post() { Id = Guid.NewGuid(), Title = "test" });
// db.SaveChanges(); //-> DbUpdateConcurrencyException: The database operation was expected to affect 1 row(s), but actually affected 0 row(s);
// Not working
// var author1 = await db.Authors.AsTracking().FirstAsync(a => a.Id == author.Id);
// author1.Posts.Add(new Post() { Id = Guid.NewGuid(), Title = "test" });
// db.SaveChanges(); //-> DbUpdateConcurrencyException: The database operation was expected to affect 1 row(s), but actually affected 0 row(s);
// Not working
// var author1 = await db.Authors.Include(a=>a.Posts).AsTracking().FirstAsync(a => a.Id == author.Id);
// author1.Posts.Add(new Post() { Id = Guid.NewGuid(), Title = "test" });
// db.SaveChanges(); //-> DbUpdateConcurrencyException: The database operation was expected to affect 1 row(s), but actually affected 0 row(s);
// this is the only way it works
// var author1 = await db.Authors.FindAsync(new object?[] { author.Id });
// var post = new Post() { Id = Guid.NewGuid(), Title = "test" };
// author1.Posts.Add(post);
// db.Entry(post).State = EntityState.Added;
// db.SaveChanges();
public class Author
{
public Guid Id { get; set; }
public List<Post> Posts { get; set; } = new();
}
public class Post
{
public Guid Id { get; set; }
public string Title { get; set; }
}
public class AuthorsDbContext : DbContext
{
public DbSet<Author> Authors { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseMySQL("Data Source=127.0.0.1;Initial Catalog=test-db-091;User Id=root;Password=DeV12345");
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Author>().HasKey(a => a.Id);
builder.Entity<Post>().HasKey(a => a.Id);
builder.Entity<Author>().HasMany(a => a.Posts).WithOne(a => a.Author).HasForeignKey(a => a.AuthorId);
builder.Entity<Post>().HasOne(a => a.Author).WithMany().HasForeignKey(a => a.AuthorId);
}
}