Efcore: Inconsistent saving behavior between EF Core 2.2 and 3.1 versions

Created on 24 Jan 2020  路  1Comment  路  Source: dotnet/efcore

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?

closed-question customer-reported

Most helpful comment

Found the solution. Have to use ValueGeneratedNever();

>All comments

Found the solution. Have to use ValueGeneratedNever();

Was this page helpful?
0 / 5 - 0 ratings