I am migrating my project from .Net Core 2.2 + EF Core 2.2.6 to .Net Core 3.1 + EF Core 3.1. But my entire project is not working correctly because of a very inconsistent saving behavior between EF Core 2.2.6 and 3.1 versions.
Created a demo app to reproduce the issue-
```c#
class Program
{
static void Main(string[] args)
{
Post p = new Post()
{
Id = Guid.NewGuid(),
PostName = "PostBlog1"
};
TestContext c = new TestContext();
c.Posts.Add(p);
c.SaveChanges();
p = c.Posts.Where(b1 => b1.Id == p.Id).FirstOrDefault();
Blog b = new Blog()
{
Id = Guid.NewGuid(),
BlogName = "TestBlog1"
};
p.Blog = b;
var entries = c.ChangeTracker.Entries();
foreach (var entry in entries)
{
Console.WriteLine($"{entry.Metadata.Name} - {entry.State}");
}
c.SaveChanges();//Fails here in .Net Core 3.1 + EF Core 3.1
Console.WriteLine("Press a any key to exit");
Console.ReadLine();
}
class TestContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("server=.;Initial Catalog=TestDb;Integrated Security=True;Encrypt=True;TrustServerCertificate=True;MultipleActiveResultSets=True");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new BlogTypeConfiguration());
modelBuilder.ApplyConfiguration(new PostTypeConfiguration());
base.OnModelCreating(modelBuilder);
}
}
class BlogTypeConfiguration : IEntityTypeConfiguration<Blog>
{
public void Configure(EntityTypeBuilder<Blog> builder)
{
builder.HasKey(b => b.Id);
builder.Property(b => b.BlogName).IsRequired();
}
}
class PostTypeConfiguration : IEntityTypeConfiguration<Post>
{
public void Configure(EntityTypeBuilder<Post> builder)
{
builder.HasKey(b => b.Id);
builder.Property(b => b.PostName).IsRequired();
builder.HasOne(p => p.Blog).WithMany().HasForeignKey("BlogId").IsRequired(false);
}
}
class Blog
{
public Guid Id { get; set; }
public string BlogName { get; set; }
}
class Post
{
public Guid Id { get; set; }
public string PostName { get; set; }
public Blog Blog { get; set; }
}
}
The above program runs perfecting fine in .Net Core 2.2 + EF Core 2.2.6 versions. The output is as below-
EFTest3._1.Program+Post - Modified
EFTest3._1.Program+Blog - **Added**
But if I upgrade to .Net Core 3.1 + EF Core 3.1, the program fails to save the DbConext after populating `Blog` object. Output -
EFTest3._1.Program+Blog - **Modified**
EFTest3._1.Program+Post - Modified
Error -
Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: 'Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.'
``
The root cause is, EF is identifying theBlogchild object asModifiedinstead ofAdded`, hence trying to update instead of insert.
Is this some new feature, if yes how to turn this off or am I missing something?
Found the solution. Have to use ValueGeneratedNever();
Most helpful comment
Found the solution. Have to use
ValueGeneratedNever();