@@ -3381,6 +3381,122 @@ public void Complex_property_json_column_is_nullable_in_TPH_hierarchy()
33813381 Assert . IsType < JsonColumn > ( jsonColumn ) ;
33823382 }
33833383
3384+ [ Fact ]
3385+ public void Complex_property_json_column_is_not_duplicated_in_TPT_child_tables ( )
3386+ {
3387+ var modelBuilder = CreateConventionModelBuilder ( ) ;
3388+
3389+ modelBuilder . Entity < TptBaseEntityWithComplexProperty > ( )
3390+ . UseTptMappingStrategy ( )
3391+ . ComplexProperty ( e => e . ComplexProperty , b => b . ToJson ( ) ) ;
3392+ modelBuilder . Entity < TptDerivedEntityWithoutComplexProperty > ( ) ;
3393+
3394+ var model = modelBuilder . FinalizeModel ( ) ;
3395+ var relationalModel = model . GetRelationalModel ( ) ;
3396+
3397+ var baseTable = relationalModel . Tables . Single ( t => t . Name == nameof ( TptBaseEntityWithComplexProperty ) ) ;
3398+ var childTable = relationalModel . Tables . Single ( t => t . Name == nameof ( TptDerivedEntityWithoutComplexProperty ) ) ;
3399+
3400+ // The JSON column for the base complex property must appear only in the base table
3401+ Assert . Contains ( baseTable . Columns , c => c . Name == nameof ( TptBaseEntityWithComplexProperty . ComplexProperty ) ) ;
3402+ Assert . DoesNotContain ( childTable . Columns , c => c . Name == nameof ( TptBaseEntityWithComplexProperty . ComplexProperty ) ) ;
3403+ }
3404+
3405+ [ Fact ]
3406+ public void Complex_property_columns_are_not_duplicated_in_TPT_child_tables ( )
3407+ {
3408+ var modelBuilder = CreateConventionModelBuilder ( ) ;
3409+
3410+ modelBuilder . Entity < TptBaseEntityWithComplexProperty > ( )
3411+ . UseTptMappingStrategy ( )
3412+ . ComplexProperty ( e => e . ComplexProperty ) ;
3413+ modelBuilder . Entity < TptDerivedEntityWithoutComplexProperty > ( ) ;
3414+
3415+ var model = modelBuilder . FinalizeModel ( ) ;
3416+ var relationalModel = model . GetRelationalModel ( ) ;
3417+
3418+ var baseTable = relationalModel . Tables . Single ( t => t . Name == nameof ( TptBaseEntityWithComplexProperty ) ) ;
3419+ var childTable = relationalModel . Tables . Single ( t => t . Name == nameof ( TptDerivedEntityWithoutComplexProperty ) ) ;
3420+
3421+ // Non-JSON complex property columns appear only on the base table.
3422+ var valueColumnName = nameof ( TptBaseEntityWithComplexProperty . ComplexProperty ) + "_" + nameof ( ComplexData . Value ) ;
3423+ var numberColumnName = nameof ( TptBaseEntityWithComplexProperty . ComplexProperty ) + "_" + nameof ( ComplexData . Number ) ;
3424+ Assert . Contains ( baseTable . Columns , c => c . Name == valueColumnName ) ;
3425+ Assert . Contains ( baseTable . Columns , c => c . Name == numberColumnName ) ;
3426+ Assert . DoesNotContain ( childTable . Columns , c => c . Name == valueColumnName ) ;
3427+ Assert . DoesNotContain ( childTable . Columns , c => c . Name == numberColumnName ) ;
3428+ }
3429+
3430+ [ Fact ]
3431+ public void Complex_property_json_column_is_created_in_every_TPC_table ( )
3432+ {
3433+ var modelBuilder = CreateConventionModelBuilder ( ) ;
3434+
3435+ modelBuilder . Entity < TpcBaseEntityWithComplexProperty > ( b =>
3436+ {
3437+ b . UseTpcMappingStrategy ( ) ;
3438+ b . ComplexProperty ( e => e . ComplexProperty , cb => cb . ToJson ( ) ) ;
3439+ } ) ;
3440+ modelBuilder . Entity < TpcDerivedEntityWithoutComplexProperty > ( ) ;
3441+
3442+ var model = modelBuilder . FinalizeModel ( ) ;
3443+ var relationalModel = model . GetRelationalModel ( ) ;
3444+
3445+ var baseTable = relationalModel . Tables . Single ( t => t . Name == nameof ( TpcBaseEntityWithComplexProperty ) ) ;
3446+ var derivedTable = relationalModel . Tables . Single ( t => t . Name == nameof ( TpcDerivedEntityWithoutComplexProperty ) ) ;
3447+
3448+ // In TPC the JSON container column appears on every concrete table.
3449+ Assert . Contains ( baseTable . Columns , c => c . Name == nameof ( TpcBaseEntityWithComplexProperty . ComplexProperty ) ) ;
3450+ Assert . Contains ( derivedTable . Columns , c => c . Name == nameof ( TpcBaseEntityWithComplexProperty . ComplexProperty ) ) ;
3451+ }
3452+
3453+ [ Fact ]
3454+ public void GetContainerColumnName_with_StoreObjectIdentifier_resolves_per_table ( )
3455+ {
3456+ var modelBuilder = CreateConventionModelBuilder ( ) ;
3457+
3458+ modelBuilder . Entity < TptBaseEntityWithComplexProperty > ( )
3459+ . UseTptMappingStrategy ( )
3460+ . ComplexProperty ( e => e . ComplexProperty , cb => cb . ToJson ( ) ) ;
3461+ modelBuilder . Entity < TptDerivedEntityWithoutComplexProperty > ( ) ;
3462+
3463+ var model = modelBuilder . FinalizeModel ( ) ;
3464+ var baseEntity = model . FindEntityType ( typeof ( TptBaseEntityWithComplexProperty ) ) ! ;
3465+ var complexProperty = baseEntity . FindComplexProperty ( nameof ( TptBaseEntityWithComplexProperty . ComplexProperty ) ) ! ;
3466+ var complexType = complexProperty . ComplexType ;
3467+
3468+ var baseTable = StoreObjectIdentifier . Table ( nameof ( TptBaseEntityWithComplexProperty ) ) ;
3469+ var childTable = StoreObjectIdentifier . Table ( nameof ( TptDerivedEntityWithoutComplexProperty ) ) ;
3470+ var unrelatedTable = StoreObjectIdentifier . Table ( "SomeOtherTable" ) ;
3471+
3472+ Assert . Equal ( nameof ( TptBaseEntityWithComplexProperty . ComplexProperty ) , complexType . GetContainerColumnName ( baseTable ) ) ;
3473+ Assert . Null ( complexType . GetContainerColumnName ( childTable ) ) ;
3474+ Assert . Null ( complexType . GetContainerColumnName ( unrelatedTable ) ) ;
3475+ }
3476+
3477+ [ Fact ]
3478+ public void GetContainerColumnName_with_StoreObjectIdentifier_returns_column_for_every_TPC_table ( )
3479+ {
3480+ var modelBuilder = CreateConventionModelBuilder ( ) ;
3481+
3482+ modelBuilder . Entity < TpcBaseEntityWithComplexProperty > ( b =>
3483+ {
3484+ b . UseTpcMappingStrategy ( ) ;
3485+ b . ComplexProperty ( e => e . ComplexProperty , cb => cb . ToJson ( ) ) ;
3486+ } ) ;
3487+ modelBuilder . Entity < TpcDerivedEntityWithoutComplexProperty > ( ) ;
3488+
3489+ var model = modelBuilder . FinalizeModel ( ) ;
3490+ var baseEntity = model . FindEntityType ( typeof ( TpcBaseEntityWithComplexProperty ) ) ! ;
3491+ var complexProperty = baseEntity . FindComplexProperty ( nameof ( TpcBaseEntityWithComplexProperty . ComplexProperty ) ) ! ;
3492+ var complexType = complexProperty . ComplexType ;
3493+
3494+ var baseTable = StoreObjectIdentifier . Table ( nameof ( TpcBaseEntityWithComplexProperty ) ) ;
3495+ var derivedTable = StoreObjectIdentifier . Table ( nameof ( TpcDerivedEntityWithoutComplexProperty ) ) ;
3496+
3497+ Assert . Equal ( nameof ( TpcBaseEntityWithComplexProperty . ComplexProperty ) , complexType . GetContainerColumnName ( baseTable ) ) ;
3498+ Assert . Equal ( nameof ( TpcBaseEntityWithComplexProperty . ComplexProperty ) , complexType . GetContainerColumnName ( derivedTable ) ) ;
3499+ }
33843500 [ Fact ]
33853501 public void Json_element_tree_is_built_for_owned_entity_json_columns ( )
33863502 {
@@ -3994,6 +4110,22 @@ private class TphEntityWithComplexProperty : TphBaseEntity
39944110 public ComplexData ComplexProperty { get ; set ; }
39954111 }
39964112
4113+ private abstract class TptBaseEntityWithComplexProperty
4114+ {
4115+ public int Id { get ; set ; }
4116+ public ComplexData ComplexProperty { get ; set ; }
4117+ }
4118+
4119+ private class TptDerivedEntityWithoutComplexProperty : TptBaseEntityWithComplexProperty ;
4120+
4121+ private class TpcBaseEntityWithComplexProperty
4122+ {
4123+ public int Id { get ; set ; }
4124+ public ComplexData ComplexProperty { get ; set ; }
4125+ }
4126+
4127+ private class TpcDerivedEntityWithoutComplexProperty : TpcBaseEntityWithComplexProperty ;
4128+
39974129 private class EntityWithJsonOwnedWithCollection
39984130 {
39994131 public int Id { get ; set ; }
0 commit comments