Skip to content

Commit

Permalink
Add TPC support for migrations
Browse files Browse the repository at this point in the history
Part of #3170
  • Loading branch information
AndriySvyryd committed Mar 17, 2022
1 parent b7518d5 commit 6a5be58
Show file tree
Hide file tree
Showing 18 changed files with 1,562 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2135,6 +2135,7 @@ protected virtual void Annotations(
foreach (var annotation in annotations)
{
// TODO: Give providers an opportunity to render these as provider-specific extension methods
// Issue #6546
builder
.AppendLine()
.Append(".Annotation(")
Expand All @@ -2157,6 +2158,7 @@ protected virtual void OldAnnotations(
foreach (var annotation in annotations)
{
// TODO: Give providers an opportunity to render these as provider-specific extension methods
// Issue #6546
builder
.AppendLine()
.Append(".OldAnnotation(")
Expand Down
71 changes: 61 additions & 10 deletions src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -675,19 +675,32 @@ protected virtual void GenerateEntityTypeAnnotations(
IEntityType entityType,
IndentedStringBuilder stringBuilder)
{
var annotationList = entityType.GetAnnotations().ToList();
IAnnotation? discriminatorPropertyAnnotation = null;
IAnnotation? discriminatorValueAnnotation = null;
IAnnotation? discriminatorMappingCompleteAnnotation = null;

var discriminatorPropertyAnnotation = annotationList.FirstOrDefault(a => a.Name == CoreAnnotationNames.DiscriminatorProperty);
var discriminatorMappingCompleteAnnotation =
annotationList.FirstOrDefault(a => a.Name == CoreAnnotationNames.DiscriminatorMappingComplete);
var discriminatorValueAnnotation = annotationList.FirstOrDefault(a => a.Name == CoreAnnotationNames.DiscriminatorValue);
foreach (var annotation in entityType.GetAnnotations())
{
switch (annotation.Name)
{
case CoreAnnotationNames.DiscriminatorProperty:
discriminatorPropertyAnnotation = annotation;
break;
case CoreAnnotationNames.DiscriminatorValue:
discriminatorValueAnnotation = annotation;
break;
case CoreAnnotationNames.DiscriminatorMappingComplete:
discriminatorMappingCompleteAnnotation = annotation;
break;
}
}

var annotations = Dependencies.AnnotationCodeGenerator
.FilterIgnoredAnnotations(entityType.GetAnnotations())
.ToDictionary(a => a.Name, a => a);

var tableNameAnnotation = annotations.Find(RelationalAnnotationNames.TableName);
if (tableNameAnnotation?.Value != null
if (tableNameAnnotation != null
|| entityType.BaseType == null)
{
var tableName = (string?)tableNameAnnotation?.Value ?? entityType.GetTableName();
Expand Down Expand Up @@ -773,7 +786,7 @@ protected virtual void GenerateEntityTypeAnnotations(
annotations.Remove(RelationalAnnotationNames.Schema);

var viewNameAnnotation = annotations.Find(RelationalAnnotationNames.ViewName);
if (viewNameAnnotation?.Value != null
if (viewNameAnnotation != null
|| entityType.BaseType == null)
{
var viewName = (string?)viewNameAnnotation?.Value ?? entityType.GetViewName();
Expand All @@ -796,7 +809,6 @@ protected virtual void GenerateEntityTypeAnnotations(
stringBuilder
.Append(", ")
.Append(Code.Literal((string)viewSchemaAnnotation.Value));
annotations.Remove(viewSchemaAnnotation.Name);
}

stringBuilder.AppendLine(");");
Expand All @@ -807,7 +819,7 @@ protected virtual void GenerateEntityTypeAnnotations(
annotations.Remove(RelationalAnnotationNames.ViewDefinitionSql);

var functionNameAnnotation = annotations.Find(RelationalAnnotationNames.FunctionName);
if (functionNameAnnotation?.Value != null
if (functionNameAnnotation != null
|| entityType.BaseType == null)
{
var functionName = (string?)functionNameAnnotation?.Value ?? entityType.GetFunctionName();
Expand All @@ -828,7 +840,7 @@ protected virtual void GenerateEntityTypeAnnotations(
}

var sqlQueryAnnotation = annotations.Find(RelationalAnnotationNames.SqlQuery);
if (sqlQueryAnnotation?.Value != null
if (sqlQueryAnnotation != null
|| entityType.BaseType == null)
{
var sqlQuery = (string?)sqlQueryAnnotation?.Value ?? entityType.GetSqlQuery();
Expand All @@ -848,6 +860,45 @@ protected virtual void GenerateEntityTypeAnnotations(
}
}

var mappingStrategyAnnotation = annotations.Find(RelationalAnnotationNames.MappingStrategy);
if (mappingStrategyAnnotation != null)
{
var strategyCall = "";
var handled = true;
if (mappingStrategyAnnotation.Value != null)
{
switch (mappingStrategyAnnotation.Value)
{
case RelationalAnnotationNames.TpcMappingStrategy:
strategyCall = "UseTpcMappingStrategy();";
break;
case RelationalAnnotationNames.TptMappingStrategy:
strategyCall = "UseTptMappingStrategy();";
break;
case RelationalAnnotationNames.TphMappingStrategy:
strategyCall = "UseTphMappingStrategy();";
break;
default:
handled = false;
break;
}
}

if (handled)
{
if (entityType.BaseType == null)
{
stringBuilder
.AppendLine()
.Append(entityTypeBuilderName)
.Append(".")
.AppendLine(strategyCall);
}

annotations.Remove(mappingStrategyAnnotation.Name);
}
}

if ((discriminatorPropertyAnnotation?.Value
?? discriminatorMappingCompleteAnnotation?.Value
?? discriminatorValueAnnotation?.Value)
Expand Down
6 changes: 3 additions & 3 deletions src/EFCore.Relational/Diagnostics/RelationalEventId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ private enum Id
ForeignKeyPropertiesMappedToUnrelatedTables,
OptionalDependentWithoutIdentifyingPropertyWarning,
DuplicateColumnOrders,
ForeignKeyTPCPrincipalWarning,
ForeignKeyTpcPrincipalWarning,
TpcStoreGeneratedIdentityWarning,

// Update events
Expand Down Expand Up @@ -752,8 +752,8 @@ private static EventId MakeValidationId(Id id)
/// This event uses the <see cref="ForeignKeyEventData" /> payload when used with a <see cref="DiagnosticSource" />.
/// </para>
/// </remarks>
public static readonly EventId ForeignKeyTPCPrincipalWarning =
MakeValidationId(Id.ForeignKeyTPCPrincipalWarning);
public static readonly EventId ForeignKeyTpcPrincipalWarning =
MakeValidationId(Id.ForeignKeyTpcPrincipalWarning);

/// <summary>
/// The PK is using store-generated values in TPC.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2832,15 +2832,15 @@ private static string ForeignKeyPropertiesMappedToUnrelatedTables(EventDefinitio
}

/// <summary>
/// Logs the <see cref="RelationalEventId.ForeignKeyTPCPrincipalWarning" /> event.
/// Logs the <see cref="RelationalEventId.ForeignKeyTpcPrincipalWarning" /> event.
/// </summary>
/// <param name="diagnostics">The diagnostics logger to use.</param>
/// <param name="foreignKey">The foreign key.</param>
public static void ForeignKeyTPCPrincipalWarning(
public static void ForeignKeyTpcPrincipalWarning(
this IDiagnosticsLogger<DbLoggerCategory.Model.Validation> diagnostics,
IForeignKey foreignKey)
{
var definition = RelationalResources.LogForeignKeyTPCPrincipal(diagnostics);
var definition = RelationalResources.LogForeignKeyTpcPrincipal(diagnostics);

if (diagnostics.ShouldLog(definition))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ public abstract class RelationalLoggingDefinitions : LoggingDefinitions
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
[EntityFrameworkInternal]
public EventDefinitionBase? LogForeignKeyTPCPrincipal;
public EventDefinitionBase? LogForeignKeyTpcPrincipal;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ private static FromSqlQueryRootExpression GenerateFromSqlQueryRoot(
if ((entityType.BaseType != null || entityType.GetDirectlyDerivedTypes().Any())
&& entityType.FindDiscriminatorProperty() == null)
{
throw new InvalidOperationException(RelationalStrings.MethodOnNonTPHRootNotSupported(memberName, entityType.DisplayName()));
throw new InvalidOperationException(RelationalStrings.MethodOnNonTphRootNotSupported(memberName, entityType.DisplayName()));
}

return new FromSqlQueryRootExpression(
Expand Down
14 changes: 7 additions & 7 deletions src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ protected virtual void ValidateDbFunctions(
&& entityType.FindDiscriminatorProperty() == null)
{
throw new InvalidOperationException(
RelationalStrings.TableValuedFunctionNonTPH(dbFunction.ModelName, entityType.DisplayName()));
RelationalStrings.TableValuedFunctionNonTph(dbFunction.ModelName, entityType.DisplayName()));
}
}

Expand Down Expand Up @@ -1056,7 +1056,7 @@ protected virtual void ValidateSharedForeignKeysCompatibility(
{
if (foreignKey.PrincipalEntityType.GetMappingStrategy() == RelationalAnnotationNames.TpcMappingStrategy)
{
logger.ForeignKeyTPCPrincipalWarning(foreignKey);
logger.ForeignKeyTpcPrincipalWarning(foreignKey);
}

var derivedTables = foreignKey.DeclaringEntityType.GetDerivedTypes()
Expand Down Expand Up @@ -1309,7 +1309,7 @@ protected override void ValidateInheritanceMapping(
&& storeObject != null)
{
throw new InvalidOperationException(
RelationalStrings.AbstractTPC(entityType.DisplayName(), storeObject));
RelationalStrings.AbstractTpc(entityType.DisplayName(), storeObject));
}
}

Expand Down Expand Up @@ -1403,9 +1403,9 @@ private static void ValidateNonTPHMapping(IEntityType rootEntityType, bool forTa
{
throw new InvalidOperationException(
forTables
? RelationalStrings.NonTPHTableClash(
? RelationalStrings.NonTphTableClash(
entityType.DisplayName(), otherType.DisplayName(), entityType.GetSchemaQualifiedTableName())
: RelationalStrings.NonTPHViewClash(
: RelationalStrings.NonTphViewClash(
entityType.DisplayName(), otherType.DisplayName(), entityType.GetSchemaQualifiedViewName()));
}

Expand Down Expand Up @@ -1439,10 +1439,10 @@ private static void ValidateTPHMapping(IEntityType rootEntityType, bool forTable
{
throw new InvalidOperationException(
forTables
? RelationalStrings.TPHTableMismatch(
? RelationalStrings.TphTableMismatch(
entityType.DisplayName(), entityType.GetSchemaQualifiedTableName(),
firstType.DisplayName(), firstType.GetSchemaQualifiedTableName())
: RelationalStrings.TPHViewMismatch(
: RelationalStrings.TphViewMismatch(
entityType.DisplayName(), entityType.GetSchemaQualifiedViewName(),
firstType.DisplayName(), firstType.GetSchemaQualifiedViewName()));
}
Expand Down
Loading

0 comments on commit 6a5be58

Please sign in to comment.