Skip to content

Commit

Permalink
Synthesize concurrency tokens for derived tables in TPC and TPT (#31979)
Browse files Browse the repository at this point in the history
Fixes #29750
  • Loading branch information
AndriySvyryd committed Oct 9, 2023
1 parent ab0509d commit b75603d
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,28 +45,27 @@ public virtual void ProcessModelFinalizing(
IConventionModelBuilder modelBuilder,
IConventionContext<IConventionModelBuilder> context)
{
var tableToEntityTypes = new Dictionary<(string Name, string? Schema), List<IConventionEntityType>>();
var tableToEntityTypes = new Dictionary<StoreObjectIdentifier, List<IConventionEntityType>>();
foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
{
var tableName = entityType.GetTableName();
if (tableName == null)
var table = StoreObjectIdentifier.Create(entityType, StoreObjectType.Table);
if (table == null)
{
continue;
}

var table = (tableName, entityType.GetSchema());
if (!tableToEntityTypes.TryGetValue(table, out var mappedTypes))
if (!tableToEntityTypes.TryGetValue(table.Value, out var mappedTypes))
{
mappedTypes = new List<IConventionEntityType>();
tableToEntityTypes[table] = mappedTypes;
tableToEntityTypes[table.Value] = mappedTypes;
}

mappedTypes.Add(entityType);
}

foreach (var ((name, schema), mappedTypes) in tableToEntityTypes)
foreach (var (table, mappedTypes) in tableToEntityTypes)
{
var concurrencyColumns = GetConcurrencyTokensMap(StoreObjectIdentifier.Table(name, schema), mappedTypes);
var concurrencyColumns = GetConcurrencyTokensMap(table, mappedTypes);
if (concurrencyColumns == null)
{
continue;
Expand All @@ -81,7 +80,7 @@ public virtual void ProcessModelFinalizing(

var foundMappedProperty = !IsConcurrencyTokenMissing(readOnlyProperties, entityType, mappedTypes)
|| entityType.GetProperties()
.Any(p => p.GetColumnName(StoreObjectIdentifier.Table(name, schema)) == concurrencyColumnName);
.Any(p => p.GetColumnName(table) == concurrencyColumnName);

if (!foundMappedProperty)
{
Expand Down Expand Up @@ -158,23 +157,23 @@ public virtual void ProcessModelFinalizing(
var nonHierarchyTypesCount = 0;
foreach (var entityType in mappedTypes)
{
if (entityType.BaseType == null
|| !mappedTypes.Contains(entityType.BaseType))
if ((entityType.BaseType == null && !mappedTypes.Any(t => t.BaseType == entityType))
|| (entityType.BaseType != null && !mappedTypes.Contains(entityType.BaseType)))
{
nonHierarchyTypesCount++;
}

concurrencyColumns = FindConcurrencyColumns(entityType, storeObject, concurrencyColumns);
}

return nonHierarchyTypesCount < 2 ? null : concurrencyColumns;
return nonHierarchyTypesCount < 1 ? null : concurrencyColumns;

static Dictionary<string, List<IReadOnlyProperty>>? FindConcurrencyColumns(
IReadOnlyTypeBase structuralType,
StoreObjectIdentifier storeObject,
Dictionary<string, List<IReadOnlyProperty>>? concurrencyColumns)
{
foreach (var property in structuralType.GetDeclaredProperties())
foreach (var property in structuralType.GetProperties())
{
if (!property.IsConcurrencyToken
|| (property.ValueGenerated & ValueGenerated.OnUpdate) == 0)
Expand All @@ -198,7 +197,7 @@ public virtual void ProcessModelFinalizing(
properties.Add(property);
}

foreach (var complexProperty in structuralType.GetDeclaredComplexProperties())
foreach (var complexProperty in structuralType.GetComplexProperties())
{
concurrencyColumns = FindConcurrencyColumns(complexProperty.ComplexType, storeObject, concurrencyColumns);
}
Expand Down
22 changes: 14 additions & 8 deletions src/EFCore.Relational/Metadata/ITable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ string ITableBase.ToDebugString(MetadataDebugStringOptions options, int indent)
{
var builder = new StringBuilder();
var indentString = new string(' ', indent);
var designTime = EntityTypeMappings.FirstOrDefault()?.TypeBase is not RuntimeEntityType;

try
{
Expand All @@ -111,8 +112,8 @@ string ITableBase.ToDebugString(MetadataDebugStringOptions options, int indent)

builder.Append(Name);

if (EntityTypeMappings.Any()
&& EntityTypeMappings.First().TypeBase is not RuntimeEntityType
if (designTime
&& EntityTypeMappings.Any()
&& IsExcludedFromMigrations)
{
builder.Append(" ExcludedFromMigrations");
Expand All @@ -132,7 +133,9 @@ string ITableBase.ToDebugString(MetadataDebugStringOptions options, int indent)
builder.Append(PrimaryKey.ToDebugString(options, indent + 2));
}

if ((options & MetadataDebugStringOptions.SingleLine) == 0 && Comment != null)
if ((options & MetadataDebugStringOptions.SingleLine) == 0
&& designTime
&& Comment != null)
{
builder
.AppendLine()
Expand Down Expand Up @@ -194,13 +197,16 @@ string ITableBase.ToDebugString(MetadataDebugStringOptions options, int indent)
}
}

var checkConstraints = CheckConstraints.ToList();
if (checkConstraints.Count != 0)
if (designTime)
{
builder.AppendLine().Append(indentString).Append(" Check constraints: ");
foreach (var checkConstraint in checkConstraints)
var checkConstraints = CheckConstraints.ToList();
if (checkConstraints.Count != 0)
{
builder.AppendLine().Append(checkConstraint.ToDebugString(options, indent + 4));
builder.AppendLine().Append(indentString).Append(" Check constraints: ");
foreach (var checkConstraint in checkConstraints)
{
builder.AppendLine().Append(checkConstraint.ToDebugString(options, indent + 4));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ await c.Database.CreateExecutionStrategy().ExecuteAsync(
var fanVersion1 = fanEntry.Property<TVersion>(propertyName).CurrentValue;
var swagVersion1 = default(TVersion);
if (mapping == Mapping.Tph) // Issue #29750
if (mapping != Mapping.Tpt) // Issue #22060
{
swagVersion1 = swagEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
Expand Down Expand Up @@ -190,7 +190,7 @@ await c.Database.CreateExecutionStrategy().ExecuteAsync(
Assert.NotEqual(fanVersion1, fanVersion2);
var swagVersion2 = default(TVersion);
if (mapping == Mapping.Tph) // Issue #29750
if (mapping != Mapping.Tpt) // Issue #22060
{
swagVersion2 = swagEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
Assert.Equal(fanVersion2, swagVersion2);
Expand Down Expand Up @@ -229,7 +229,7 @@ await c.Database.CreateExecutionStrategy().ExecuteAsync(
var fanVersion3 = fanEntry.Property<TVersion>(propertyName).CurrentValue;
Assert.NotEqual(fanVersion2, fanVersion3);
if (mapping == Mapping.Tph) // Issue #29750
if (mapping != Mapping.Tpt) // Issue #22060
{
var swagVersion3 = swagEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
Assert.Equal(fanVersion3, swagVersion3);
Expand Down Expand Up @@ -261,7 +261,7 @@ await c.Database.CreateExecutionStrategy().ExecuteAsync(
var circuitVersion1 = circuitEntry.Property<TVersion>(propertyName).CurrentValue;
var cityVersion1 = default(TVersion);
if (mapping == Mapping.Tph) // Issue #29750
if (mapping != Mapping.Tpt) // Issue #22060
{
cityVersion1 = cityEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
Expand Down Expand Up @@ -302,7 +302,7 @@ await c.Database.CreateExecutionStrategy().ExecuteAsync(
Assert.NotEqual(circuitVersion1, circuitVersion2);
var cityVersion2 = default(TVersion);
if (mapping == Mapping.Tph) // Issue #29750
if (mapping != Mapping.Tpt) // Issue #22060
{
cityVersion2 = cityEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
Assert.Equal(circuitVersion2, cityVersion2);
Expand Down Expand Up @@ -341,7 +341,7 @@ await c.Database.CreateExecutionStrategy().ExecuteAsync(
var circuitVersion3 = circuitEntry.Property<TVersion>(propertyName).CurrentValue;
Assert.NotEqual(circuitVersion2, circuitVersion3);
if (mapping == Mapping.Tph) // Issue #29750
if (mapping != Mapping.Tpt) // Issue #22060
{
var cityVersion3 = cityEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
Assert.Equal(circuitVersion3, cityVersion3);
Expand Down

0 comments on commit b75603d

Please sign in to comment.