Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In-Memory concurrency check is not doing a sequence check when using a byte array type #12214

Closed
tsangste opened this issue Jun 2, 2018 · 1 comment
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported regression type-bug
Milestone

Comments

@tsangste
Copy link

tsangste commented Jun 2, 2018

Describe what is not working as expected.

I am using a byte array for my concurrency check and when using automapper to go from my dto to my ef entity object it causes the following error when saving with the in-memory provider for my tests:

Exception thrown: 'Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException' in ConcurrencyTest.dll
An unhandled exception of type 'Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException' occurred in ConcurrencyTest.dll
Conflicts were detected for instance of entity type 'Customer' on the concurrency token properties {'RowVersion'}. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting values.

The error has started occurring when upgrading my project to 2.1. I narrowed it to #10158 where concurrency token checks were enabled for the in-memory provider. After reviewing the code I notice it is doing a equals check and possibly might require a equal sequence check if its a byte array?

Steps to reproduce

using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Microsoft.EntityFrameworkCore;

namespace ConcurrencyTest
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var customer = new Customer
            {
                FirstName = "John",
                LastName = "Smith",
                RowVersion = Convert.FromBase64String("AAAAAAAQexM=")
            };

            using (var context = new DatabaseContext())
            {
                context.Customers.Add(customer);
                context.SaveChanges();
            }

            using (var context = new DatabaseContext())
            {
                try
                {
                    var currentCustomer = context.Customers.Single(c => c.Id == customer.Id);

                    currentCustomer.FirstName = "Dr";
                    currentCustomer.LastName = "Who";

                    // Set to the same sequence byte[] value to simulate originalvalue being set from another object i.e. if a dto mapping occured
                    context.Entry(currentCustomer).Property("RowVersion").OriginalValue = Convert.FromBase64String("AAAAAAAQexM=");

                    context.SaveChanges();
                }
                catch (DbUpdateConcurrencyException e)
                {
                    Console.WriteLine(e);
                    throw;
                }
            }
        }
    }

    public class DatabaseContext : DbContext
    {
        public DbSet<Customer> Customers { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
                .UseInMemoryDatabase("ConcurrencyTest");
        }
    }

    public class Customer
    {
        [Key]
        public int Id { get; set; }

        public string FirstName { get; set; }

        public string LastName { get; set; }

        [ConcurrencyCheck]
        public byte[] RowVersion { get; set; }
    }
}

Further technical details

EF Core version: 2.1
Database Provider: Microsoft.EntityFrameworkCore.InMemory
Operating system: Windows 10
IDE: Visual Studio 2017 15.7.3

@ajcvickers ajcvickers self-assigned this Jun 4, 2018
@ajcvickers ajcvickers added this to the 2.1.3 milestone Jun 4, 2018
ajcvickers added a commit that referenced this issue Jun 21, 2018
Fixes #12214

Fix is to use structural equality all the time for concurrency checks. This matches more closely the way the check works on real database systems.
@ajcvickers ajcvickers added Servicing-consider closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. patch-approved and removed Servicing-consider labels Jun 21, 2018
@ajcvickers
Copy link
Member

@ajcvickers This issue is approved for patch and the release\2.1 branch is now open for merging. Please ensure:

  • The appropriate changes get into both the release and dev branches
  • Quirking is included for the release branch only

ajcvickers added a commit that referenced this issue Jun 27, 2018
Fixes #12214

Fix is to use structural equality all the time for concurrency checks. This matches more closely the way the check works on real database systems.
ajcvickers added a commit that referenced this issue Jun 27, 2018
Fixes #12214

Fix is to use structural equality all the time for concurrency checks. This matches more closely the way the check works on real database systems.
@ajcvickers ajcvickers removed their assignment Sep 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported regression type-bug
Projects
None yet
Development

No branches or pull requests

2 participants