Skip to content

Commit

Permalink
Add entity-splitting model building support
Browse files Browse the repository at this point in the history
Allow specifying different column names per table in TPT, TPC or entity splitting

Part of #620
Fixes #19811
  • Loading branch information
AndriySvyryd committed Jun 1, 2022
1 parent 5fc5762 commit 65fe492
Show file tree
Hide file tree
Showing 102 changed files with 7,369 additions and 2,970 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ private void GenerateKeyAttribute(IProperty property)

private void GenerateColumnAttribute(IProperty property)
{
var columnName = property.GetColumnBaseName();
var columnName = property.GetColumnName();
var columnType = property.GetConfiguredColumnType();

var delimitedColumnName = columnName != null && columnName != property.Name ? _code.Literal(columnName) : null;
Expand Down
3 changes: 2 additions & 1 deletion src/EFCore.Relational/Design/AnnotationCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class AnnotationCodeGenerator : IAnnotationCodeGenerator
RelationalAnnotationNames.Triggers,
RelationalAnnotationNames.Sequences,
RelationalAnnotationNames.DbFunctions,
RelationalAnnotationNames.MappingFragments,
RelationalAnnotationNames.RelationalOverrides
};

Expand Down Expand Up @@ -161,7 +162,7 @@ public virtual void RemoveAnnotationsHandledByConventions(
IProperty property,
IDictionary<string, IAnnotation> annotations)
{
var columnName = property.GetColumnBaseName();
var columnName = property.GetColumnName();
if (columnName == property.Name)
{
annotations.Remove(RelationalAnnotationNames.ColumnName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,25 @@ public override void Generate(IEntityType entityType, CSharpRuntimeAnnotationCod
annotations[RelationalAnnotationNames.SqlQuery] = entityType.GetSqlQuery();
annotations[RelationalAnnotationNames.FunctionName] = entityType.GetFunctionName();

if (annotations.TryGetAndRemove(
RelationalAnnotationNames.MappingFragments,
out Dictionary<StoreObjectIdentifier, IEntityTypeMappingFragment> overrides))
{
AddNamespace(typeof(Dictionary<StoreObjectIdentifier, IEntityTypeMappingFragment>), parameters.Namespaces);
AddNamespace(typeof(RuntimeEntityTypeMappingFragment), parameters.Namespaces);
AddNamespace(typeof(StoreObjectIdentifier), parameters.Namespaces);
var fragmentsVariable = Dependencies.CSharpHelper.Identifier("fragments", parameters.ScopeVariables, capitalize: false);
parameters.MainBuilder
.Append("var ").Append(fragmentsVariable).AppendLine(" = new Dictionary<StoreObjectIdentifier, IEntityTypeMappingFragment>();");

foreach (var (key, value) in overrides.OrderBy(pair => pair.Key.Name, StringComparer.Ordinal))
{
Create(value, key, fragmentsVariable, parameters);
}

GenerateSimpleAnnotation(RelationalAnnotationNames.MappingFragments, fragmentsVariable, parameters);
}

if (annotations.TryGetAndRemove(
RelationalAnnotationNames.Triggers,
out SortedDictionary<string, ITrigger> triggers))
Expand All @@ -346,6 +365,37 @@ public override void Generate(IEntityType entityType, CSharpRuntimeAnnotationCod

base.Generate(entityType, parameters);
}

private void Create(
IEntityTypeMappingFragment fragments,
StoreObjectIdentifier storeObject,
string fragmentsVariable,
CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
{
var code = Dependencies.CSharpHelper;
var overrideVariable =
code.Identifier(parameters.TargetName + Capitalize(storeObject.Name), parameters.ScopeVariables, capitalize: false);
var mainBuilder = parameters.MainBuilder;
mainBuilder
.Append("var ").Append(overrideVariable).AppendLine(" = new RuntimeEntityTypeMappingFragment(").IncrementIndent()
.Append(parameters.TargetName).AppendLine(",");

AppendLiteral(storeObject, mainBuilder, code);
mainBuilder.AppendLine(",")
.Append(code.Literal(fragments.IsTableExcludedFromMigrations)).AppendLine(");").DecrementIndent();

CreateAnnotations(
fragments,
GenerateOverrides,
parameters with { TargetName = overrideVariable });

mainBuilder.Append(fragmentsVariable).Append("[");
AppendLiteral(storeObject, mainBuilder, code);

mainBuilder
.Append("] = ")
.Append(overrideVariable).AppendLine(";");
}

private void Create(ITrigger trigger, string triggersVariable, CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
{
Expand Down Expand Up @@ -410,16 +460,18 @@ public override void Generate(IProperty property, CSharpRuntimeAnnotationCodeGen

if (annotations.TryGetAndRemove(
RelationalAnnotationNames.RelationalOverrides,
out SortedDictionary<StoreObjectIdentifier, object> overrides))
out Dictionary<StoreObjectIdentifier, IRelationalPropertyOverrides> overrides))
{
parameters.Namespaces.Add(typeof(SortedDictionary<StoreObjectIdentifier, object>).Namespace!);
AddNamespace(typeof(Dictionary<StoreObjectIdentifier, IRelationalPropertyOverrides>), parameters.Namespaces);
AddNamespace(typeof(RuntimeRelationalPropertyOverrides), parameters.Namespaces);
AddNamespace(typeof(StoreObjectIdentifier), parameters.Namespaces);
var overridesVariable = Dependencies.CSharpHelper.Identifier("overrides", parameters.ScopeVariables, capitalize: false);
parameters.MainBuilder
.Append("var ").Append(overridesVariable).AppendLine(" = new SortedDictionary<StoreObjectIdentifier, object>();");
.Append("var ").Append(overridesVariable).AppendLine(" = new Dictionary<StoreObjectIdentifier, IRelationalPropertyOverrides>();");

foreach (var (key, value) in overrides)
foreach (var (key, value) in overrides.OrderBy(pair => pair.Key.Name, StringComparer.Ordinal))
{
Create((IRelationalPropertyOverrides)value, key, overridesVariable, parameters);
Create(value, key, overridesVariable, parameters);
}

GenerateSimpleAnnotation(RelationalAnnotationNames.RelationalOverrides, overridesVariable, parameters);
Expand All @@ -441,7 +493,10 @@ private void Create(
var mainBuilder = parameters.MainBuilder;
mainBuilder
.Append("var ").Append(overrideVariable).AppendLine(" = new RuntimeRelationalPropertyOverrides(").IncrementIndent()
.Append(parameters.TargetName).AppendLine(",")
.Append(parameters.TargetName).AppendLine(",");
AppendLiteral(storeObject, mainBuilder, code);

mainBuilder.AppendLine(",")
.Append(code.Literal(overrides.ColumnNameOverridden)).AppendLine(",")
.Append(code.UnknownLiteral(overrides.ColumnName)).AppendLine(");").DecrementIndent();

Expand All @@ -450,29 +505,8 @@ private void Create(
GenerateOverrides,
parameters with { TargetName = overrideVariable });

mainBuilder.Append(overridesVariable).Append("[StoreObjectIdentifier.");

switch (storeObject.StoreObjectType)
{
case StoreObjectType.Table:
mainBuilder
.Append("Table(").Append(code.Literal(storeObject.Name))
.Append(", ").Append(code.UnknownLiteral(storeObject.Schema)).Append(")");
break;
case StoreObjectType.View:
mainBuilder
.Append("View(").Append(code.Literal(storeObject.Name))
.Append(", ").Append(code.UnknownLiteral(storeObject.Schema)).Append(")");
break;
case StoreObjectType.SqlQuery:
mainBuilder
.Append("SqlQuery(").Append(code.Literal(storeObject.Name)).Append(")");
break;
case StoreObjectType.Function:
mainBuilder
.Append("DbFunction(").Append(code.Literal(storeObject.Name)).Append(")");
break;
}
mainBuilder.Append(overridesVariable).Append("[");
AppendLiteral(storeObject, mainBuilder, code);

mainBuilder
.Append("] = ")
Expand Down Expand Up @@ -553,4 +587,33 @@ private static string Capitalize(string @string)
return char.ToUpperInvariant(@string[0]) + @string[1..];
}
}

private static void AppendLiteral(StoreObjectIdentifier storeObject, IndentedStringBuilder builder, ICSharpHelper code)
{
builder.Append("StoreObjectIdentifier.");
switch (storeObject.StoreObjectType)
{
case StoreObjectType.Table:
builder
.Append("Table(").Append(code.Literal(storeObject.Name))
.Append(", ").Append(code.UnknownLiteral(storeObject.Schema)).Append(")");
break;
case StoreObjectType.View:
builder
.Append("View(").Append(code.Literal(storeObject.Name))
.Append(", ").Append(code.UnknownLiteral(storeObject.Schema)).Append(")");
break;
case StoreObjectType.SqlQuery:
builder
.Append("SqlQuery(").Append(code.Literal(storeObject.Name)).Append(")");
break;
case StoreObjectType.Function:
builder
.Append("DbFunction(").Append(code.Literal(storeObject.Name)).Append(")");
break;
default:
Check.DebugAssert(false, "Unexpected StoreObjectType: " + storeObject.StoreObjectType);
break;
}
}
}
Loading

0 comments on commit 65fe492

Please sign in to comment.