Skip to content

Conflict with RowVersion/Concurrency Token in TPH with Owned Entity as JSON (ValidateJsonProperties throws exception) #37274

@Schaeri

Description

@Schaeri

Bug description

After upgrading from EF Core 9.x to 10.0.0, an exception is thrown during model building (e.g., EnsureCreated or during migrations) when the following combination is used:

  • TPH inheritance (base class + derived class)
  • A traditional RowVersion column in the base class (IsRowVersion / IsConcurrencyToken)
  • A derived class containing an owned type that is mapped to JSON using ToJson()

This model works correctly in EF Core 9. Starting with EF Core 10, it fails with the following exception:

System.InvalidOperationException: Property 'OwnedEntity._TableSharingConcurrencyTokenConvention_RowVersion' cannot have both a column name ('RowVersion') and a JSON property name ('_TableSharingConcurrencyTokenConvention_RowVersion') configured. Properties in JSON-mapped types should use JSON property names, not column names.

Expected Behavior

The model should be built without throwing an exception.
The RowVersion in the base class should work as a standard timestamp/rowversion column, and the owned JSON object should be validated independently without inheriting concurrency metadata.

Actual Behavior

During model creation (dbContext.Database.EnsureCreated()), EF Core throws an InvalidOperationException (full stack trace included in the sample project).
This prevents both model creation and migrations.

Issue.zip

Your code

// Sample Entities

public abstract class BaseEntity
{
    public int Id { get; set; }

    public string Name { get; set; } = string.Empty;

    public long RowVersion { get; set; }
}

public class DerivedEntity : BaseEntity
{
    public OwnedEntity Owned { get; set; } = new();
}

public class OwnedEntity
{
    public string Description { get; set; } = "Any";
}

// DB Context --> leads to the error on EF Core 10
public class MyDbContext(DbContextOptions<MyDbContext> dbContextOptions) : DbContext(dbContextOptions)
{
    protected override void OnModelCreating(
        ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<BaseEntity>(b =>
        {
            b.HasKey(e => e.Id);
            
            b.Property(e => e.RowVersion).IsRowVersion().IsConcurrencyToken();

            b.Property(e => e.Name).HasMaxLength(100).IsRequired();

            b.HasDiscriminator<string>("Type")
                .HasValue<DerivedEntity>(nameof(DerivedEntity));
        });

        modelBuilder.Entity<DerivedEntity>(b =>
        {
            b.OwnsOne(x => x.Owned, ob =>
            {
                ob.ToJson();
                ob.Property(o => o.Description).HasMaxLength(200).IsRequired();
            });
        });
    }
}

// DB Context --> workaround
public class MyDbContext(DbContextOptions<MyDbContext> dbContextOptions) : DbContext(dbContextOptions)
{
    protected override void OnModelCreating(
        ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<BaseEntity>(b =>
        {
            b.HasKey(e => e.Id);
            
            //b.Property(e => e.RowVersion).IsRowVersion().IsConcurrencyToken();
            b.Ignore(x => x.RowVersion);

            b.Property(e => e.Name).HasMaxLength(100).IsRequired();

            b.HasDiscriminator<string>("Type")
                .HasValue<DerivedEntity>(nameof(DerivedEntity));
        });

        modelBuilder.Entity<DerivedEntity>(b =>
        {
            // Moved from base entity to derived entity
            b.Property(e => e.RowVersion).IsRowVersion().IsConcurrencyToken();
            
            b.OwnsOne(x => x.Owned, ob =>
            {
                ob.ToJson();
                ob.Property(o => o.Description).HasMaxLength(200).IsRequired();
            });
        });
    }
}

Stack traces

Unhandled exception. System.InvalidOperationException: Property 'OwnedEntity._TableSharingConcurrencyTokenConvention_RowVersion' cannot have both a column name ('RowVersion') and a JSON property name ('_TableSharingConcurrencyTokenConvention_RowVersion') configured. Properties in JSON-mapped types should use JSON property names, not column names.
   at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.ValidateJsonProperties(IConventionTypeBase typeBase)
   at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.ValidateJsonEntityProperties(StoreObjectIdentifier& storeObject, IEntityType jsonEntityType)
   at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.ValidateJsonEntities(IModel model, IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.SqlServer.Infrastructure.Internal.SqlServerModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelRuntimeInitializer.Initialize(IModel model, Boolean designTime, IDiagnosticsLogger`1 validationLogger)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, ModelCreationDependencies modelCreationDependencies, Boolean designTime)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, ModelCreationDependencies modelCreationDependencies, Boolean designTime)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel(Boolean designTime)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
   at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__8_4(IServiceProvider p)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass2_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier serviceIdentifier, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.get_ContextServices()
   at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
   at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetService(IInfrastructure`1 accessor, Type serviceType)
   at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.get_Dependencies()
   at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.EnsureCreated()
   at Program.<Main>$(String[] args) in C:\Users\rs\Desktop\EFCore10RowIssue\EFCore10RowIssue\Program.cs:line 11

Verbose output


EF Core version

10.0.0

Database provider

Microsoft.EntityFrameworkCore.SqlServer

Target framework

.Net 10.0

Operating system

Windows 11

IDE

Jetbrain Rider

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions