Skip to content

IsConcurrencyToken is not working when used in Json owned entity #35934

Open
@KyMback

Description

@KyMback

Bug description

When IsConcurrencyToken is used with property in Owned entity which is mapped to json column => incorrect sql is generated. For the provided code I see the following in logs:

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (6ms) [Parameters=[@p0='?' (Size = 63), @p1='?' (DbType = Guid)], CommandType='Text', CommandTimeout='30']
      SET IMPLICIT_TRANSACTIONS OFF;
      SET NOCOUNT ON;
      UPDATE [Entities] SET [Owned] = @p0
      OUTPUT 1
      WHERE [Id] = @p1;

I expect to see smth like ...WHERE [id] = @p1 AND JSON_VALUE('$.Version') = @p2 where @p2 is old concurrency token value

Your code

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

var services = new ServiceCollection()
    .AddLogging(e => e.AddConsole())
    .AddDbContext<AppDbContext>()
    .BuildServiceProvider();

void Initialize()
{
    using var scope1 = services.CreateScope();
    var dbContext = scope1.ServiceProvider.GetRequiredService<AppDbContext>();
    
    dbContext.Database.EnsureDeleted();
    dbContext.Database.EnsureCreated();

    dbContext.Entities.Add(new Entity
    {
        Owned = new OwnedEntity()
        {
            Text = "123",
            Version = Guid.NewGuid(),
        }
    });

    dbContext.SaveChanges();
}

Initialize();
var dbContext = services.CreateScope().ServiceProvider.GetRequiredService<AppDbContext>();

var entity = dbContext.Entities.First();

entity.Owned = new OwnedEntity()
{
    Text = "444",
    Version = Guid.NewGuid(),
};

dbContext.Entities.Update(entity);
dbContext.SaveChanges();

public class AppDbContext : DbContext
{
    private readonly ILoggerFactory _loggerFactory;

    public AppDbContext(ILoggerFactory loggerFactory, DbContextOptions<AppDbContext> options) : base(options)
    {
        _loggerFactory = loggerFactory;
    }

    public DbSet<Entity> Entities { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseSqlServer("")
            .UseLoggerFactory(_loggerFactory);
        base.OnConfiguring(optionsBuilder);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Entity>(n =>
        {
            n.ToTable("Entities").HasKey(e => e.Id);
            n.OwnsOne(e => e.Owned, n1 =>
            {
                n1.ToJson("Owned");
                n1.Property(e => e.Text).HasMaxLength(250).IsRequired();
                n1.Property(e => e.Version).IsConcurrencyToken().IsRequired();
            });
        });
    }
}

public class Entity
{
    public Guid Id { get; set; }
    public OwnedEntity Owned { get; set; }
}

public class OwnedEntity
{
    public string Text { get; set; }
    public Guid Version { get; set; }
}

Stack traces


Verbose output


EF Core version

9.0.4

Database provider

Microsoft.EntityFrameworkCore.SqlServer

Target framework

.NET 9

Operating system

Windows 11

IDE

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions