Skip to content

Commit

Permalink
Add non-owned table splitting support to query
Browse files Browse the repository at this point in the history
Materialize owned entities with all null properties if they are being referenced by other entities

Fixes #16032
  • Loading branch information
AndriySvyryd committed Aug 17, 2019
1 parent 7d2c9c8 commit 07e6609
Show file tree
Hide file tree
Showing 41 changed files with 1,934 additions and 449 deletions.
2 changes: 1 addition & 1 deletion src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static class CosmosEntityTypeExtensions
/// <returns> The name of the container to which the entity type is mapped. </returns>
public static string GetCosmosContainer([NotNull] this IEntityType entityType) =>
entityType.BaseType != null
? entityType.RootType().GetCosmosContainer()
? entityType.GetRootType().GetCosmosContainer()
: (string)entityType[CosmosAnnotationNames.ContainerName]
?? GetCosmosDefaultContainer(entityType);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ protected virtual void GenerateEntityTypeAnnotations(
if (discriminatorValueAnnotation?.Value != null)
{
var value = discriminatorValueAnnotation.Value;
var discriminatorProperty = entityType.RootType().GetDiscriminatorProperty();
var discriminatorProperty = entityType.GetRootType().GetDiscriminatorProperty();
if (discriminatorProperty != null)
{
var valueConverter = FindValueConverter(discriminatorProperty);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ private Expression BindProperty(Expression source, string propertyName, Type typ
var entityType = entityProjection.EntityType;
if (convertedType != null)
{
entityType = entityType.RootType().GetDerivedTypesInclusive()
entityType = entityType.GetRootType().GetDerivedTypesInclusive()
.FirstOrDefault(et => et.ClrType == convertedType);

if (entityType == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static class RelationalEntityTypeExtensions
/// <returns> The name of the table to which the entity type is mapped. </returns>
public static string GetTableName([NotNull] this IEntityType entityType) =>
entityType.BaseType != null
? entityType.RootType().GetTableName()
? entityType.GetRootType().GetTableName()
: (string)entityType[RelationalAnnotationNames.TableName]
?? GetDefaultTableName(entityType);

Expand Down Expand Up @@ -87,7 +87,7 @@ public static void SetTableName(
/// <returns> The database schema that contains the mapped table. </returns>
public static string GetSchema([NotNull] this IEntityType entityType) =>
entityType.BaseType != null
? entityType.RootType().GetSchema()
? entityType.GetRootType().GetSchema()
: (string)entityType[RelationalAnnotationNames.Schema]
?? GetDefaultSchema(entityType);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ protected virtual void ValidateSharedTableCompatibility(
|| (mappedType.FindPrimaryKey() != null && mappedType.FindForeignKeys(mappedType.FindPrimaryKey().Properties)
.Any(
fk => fk.PrincipalKey.IsPrimaryKey()
&& fk.PrincipalEntityType.RootType() != mappedType
&& fk.PrincipalEntityType.GetRootType() != mappedType
&& unvalidatedTypes.Contains(fk.PrincipalEntityType))))
{
continue;
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore.Relational/Metadata/Internal/TableMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public virtual IEntityType GetRootType()
&& (t.FindDeclaredPrimaryKey() == null || t.FindForeignKeys(t.FindDeclaredPrimaryKey().Properties)
.All(
fk => !fk.PrincipalKey.IsPrimaryKey()
|| fk.PrincipalEntityType.RootType() == t
|| fk.PrincipalEntityType.GetRootType() == t
|| t.GetTableName() != fk.PrincipalEntityType.GetTableName()
|| t.GetSchema() != fk.PrincipalEntityType.GetSchema())));

Expand Down
30 changes: 15 additions & 15 deletions src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ private static IEnumerable<IProperty> GetSortedProperties(IEntityType entityType

foreach (var definingForeignKey in entityType.GetDeclaredReferencingForeignKeys()
.Where(
fk => fk.DeclaringEntityType.RootType() != entityType.RootType()
fk => fk.DeclaringEntityType.GetRootType() != entityType.GetRootType()
&& fk.DeclaringEntityType.GetTableName() == entityType.GetTableName()
&& fk == fk.DeclaringEntityType
.FindForeignKey(
Expand Down Expand Up @@ -913,7 +913,7 @@ private static string GetDefiningNavigationName(IEntityType entityType)
/// </summary>
protected virtual IEnumerable<MigrationOperation> Diff([NotNull] IProperty source, [NotNull] IProperty target, [NotNull] DiffContext diffContext)
{
var targetEntityType = target.DeclaringEntityType.RootType();
var targetEntityType = target.DeclaringEntityType.GetRootType();

if (source.GetColumnName() != target.GetColumnName())
{
Expand Down Expand Up @@ -985,7 +985,7 @@ protected virtual IEnumerable<MigrationOperation> Add(
[NotNull] DiffContext diffContext,
bool inline = false)
{
var targetEntityType = target.DeclaringEntityType.RootType();
var targetEntityType = target.DeclaringEntityType.GetRootType();

var operation = new AddColumnOperation
{
Expand All @@ -1009,7 +1009,7 @@ protected virtual IEnumerable<MigrationOperation> Add(
/// </summary>
protected virtual IEnumerable<MigrationOperation> Remove([NotNull] IProperty source, [NotNull] DiffContext diffContext)
{
var sourceEntityType = source.DeclaringEntityType.RootType();
var sourceEntityType = source.DeclaringEntityType.GetRootType();

var operation = new DropColumnOperation
{
Expand Down Expand Up @@ -1102,7 +1102,7 @@ protected virtual IEnumerable<MigrationOperation> Diff(
/// </summary>
protected virtual IEnumerable<MigrationOperation> Add([NotNull] IKey target, [NotNull] DiffContext diffContext)
{
var targetEntityType = target.DeclaringEntityType.RootType();
var targetEntityType = target.DeclaringEntityType.GetRootType();
var columns = GetColumns(target.Properties);

MigrationOperation operation;
Expand Down Expand Up @@ -1142,7 +1142,7 @@ protected virtual IEnumerable<MigrationOperation> Remove(
[NotNull] IKey source,
[NotNull] DiffContext diffContext)
{
var sourceEntityType = source.DeclaringEntityType.RootType();
var sourceEntityType = source.DeclaringEntityType.GetRootType();

MigrationOperation operation;
if (source.IsPrimaryKey())
Expand Down Expand Up @@ -1218,8 +1218,8 @@ protected virtual IEnumerable<MigrationOperation> Diff(
/// </summary>
protected virtual IEnumerable<MigrationOperation> Add([NotNull] IForeignKey target, [NotNull] DiffContext diffContext)
{
var targetEntityType = target.DeclaringEntityType.RootType();
var targetPrincipalEntityType = target.PrincipalEntityType.RootType();
var targetEntityType = target.DeclaringEntityType.GetRootType();
var targetPrincipalEntityType = target.PrincipalEntityType.GetRootType();

var operation = new AddForeignKeyOperation
{
Expand Down Expand Up @@ -1253,7 +1253,7 @@ protected virtual IEnumerable<MigrationOperation> Add([NotNull] IForeignKey targ
/// </summary>
protected virtual IEnumerable<MigrationOperation> Remove([NotNull] IForeignKey source, [NotNull] DiffContext diffContext)
{
var declaringRootEntityType = source.DeclaringEntityType.RootType();
var declaringRootEntityType = source.DeclaringEntityType.GetRootType();

var dropTableOperation = diffContext.FindDrop(declaringRootEntityType);
if (dropTableOperation == null)
Expand Down Expand Up @@ -1316,7 +1316,7 @@ protected virtual IEnumerable<MigrationOperation> Diff(
[NotNull] IIndex target,
[NotNull] DiffContext diffContext)
{
var targetEntityType = target.DeclaringEntityType.RootType();
var targetEntityType = target.DeclaringEntityType.GetRootType();
var sourceName = source.GetName();
var targetName = target.GetName();

Expand All @@ -1342,7 +1342,7 @@ protected virtual IEnumerable<MigrationOperation> Add(
[NotNull] IIndex target,
[NotNull] DiffContext diffContext)
{
var targetEntityType = target.DeclaringEntityType.RootType();
var targetEntityType = target.DeclaringEntityType.GetRootType();

var operation = new CreateIndexOperation
{
Expand All @@ -1366,7 +1366,7 @@ protected virtual IEnumerable<MigrationOperation> Add(
/// </summary>
protected virtual IEnumerable<MigrationOperation> Remove([NotNull] IIndex source, [NotNull] DiffContext diffContext)
{
var sourceEntityType = source.DeclaringEntityType.RootType();
var sourceEntityType = source.DeclaringEntityType.GetRootType();

var operation = new DropIndexOperation
{
Expand Down Expand Up @@ -1422,7 +1422,7 @@ protected virtual IEnumerable<MigrationOperation> Diff(
/// </summary>
protected virtual IEnumerable<MigrationOperation> Add([NotNull] ICheckConstraint target, [NotNull] DiffContext diffContext)
{
var targetEntityType = target.EntityType.RootType();
var targetEntityType = target.EntityType.GetRootType();

var operation = new CreateCheckConstraintOperation
{
Expand All @@ -1446,7 +1446,7 @@ protected virtual IEnumerable<MigrationOperation> Add([NotNull] ICheckConstraint
/// </summary>
protected virtual IEnumerable<MigrationOperation> Remove([NotNull] ICheckConstraint source, [NotNull] DiffContext diffContext)
{
var sourceEntityType = source.EntityType.RootType();
var sourceEntityType = source.EntityType.GetRootType();

var operation = new DropCheckConstraintOperation
{
Expand Down Expand Up @@ -2011,7 +2011,7 @@ protected virtual IEnumerable<MigrationOperation> GetDataOperations([NotNull] Di
batchInsertOperation = null;
}

if (c.Entries.All(e => diffContext.FindDrop(e.EntityType.RootType()) == null))
if (c.Entries.All(e => diffContext.FindDrop(e.EntityType.GetRootType()) == null))
{
yield return new DeleteDataOperation
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@ private ShapedQueryExpression CreateShapedQueryExpression(Type elementType, stri
}

private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType entityType, SelectExpression selectExpression)
{
return new ShapedQueryExpression(
=> new ShapedQueryExpression(
selectExpression,
new EntityShaperExpression(
entityType,
Expand All @@ -110,7 +109,6 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent
new ProjectionMember(),
typeof(ValueBuffer)),
false));
}

protected override ShapedQueryExpression TranslateAll(ShapedQueryExpression source, LambdaExpression predicate)
{
Expand Down Expand Up @@ -1047,7 +1045,7 @@ private Expression Expand(Expression source, MemberIdentity member)
var entityType = entityShaperExpression.EntityType;
if (convertedType != null)
{
entityType = entityType.RootType().GetDerivedTypesInclusive()
entityType = entityType.GetRootType().GetDerivedTypesInclusive()
.FirstOrDefault(et => et.ClrType == convertedType);

if (entityType == null)
Expand All @@ -1073,28 +1071,26 @@ private Expression Expand(Expression source, MemberIdentity member)
return null;
}


var foreignKey = navigation.ForeignKey;
if (navigation.IsCollection())
{
var innerSelectExpression = _sqlExpressionFactory.Select(targetEntityType);
var innerShapedQuery = CreateShapedQueryExpression(targetEntityType, innerSelectExpression);

var makeNullable = navigation.ForeignKey.PrincipalKey.Properties
.Concat(navigation.ForeignKey.Properties)
var makeNullable = foreignKey.PrincipalKey.Properties
.Concat(foreignKey.Properties)
.Select(p => p.ClrType)
.Any(t => t.IsNullableType());

var outerKey = CreateKeyAccessExpression(
entityShaperExpression,
var outerKey = entityShaperExpression.CreateKeyAccessExpression(
navigation.IsDependentToPrincipal()
? navigation.ForeignKey.Properties
: navigation.ForeignKey.PrincipalKey.Properties,
? foreignKey.Properties
: foreignKey.PrincipalKey.Properties,
makeNullable);
var innerKey = CreateKeyAccessExpression(
innerShapedQuery.ShaperExpression,
var innerKey = innerShapedQuery.ShaperExpression.CreateKeyAccessExpression(
navigation.IsDependentToPrincipal()
? navigation.ForeignKey.PrincipalKey.Properties
: navigation.ForeignKey.Properties,
? foreignKey.PrincipalKey.Properties
: foreignKey.Properties,
makeNullable);

var correlationPredicate = _sqlTranslator.Translate(Expression.Equal(outerKey, innerKey));
Expand All @@ -1115,22 +1111,20 @@ private Expression Expand(Expression source, MemberIdentity member)
var innerSelectExpression = _sqlExpressionFactory.Select(targetEntityType);
var innerShapedQuery = CreateShapedQueryExpression(targetEntityType, innerSelectExpression);

var makeNullable = navigation.ForeignKey.PrincipalKey.Properties
.Concat(navigation.ForeignKey.Properties)
var makeNullable = foreignKey.PrincipalKey.Properties
.Concat(foreignKey.Properties)
.Select(p => p.ClrType)
.Any(t => t.IsNullableType());

var outerKey = CreateKeyAccessExpression(
entityShaperExpression,
var outerKey = entityShaperExpression.CreateKeyAccessExpression(
navigation.IsDependentToPrincipal()
? navigation.ForeignKey.Properties
: navigation.ForeignKey.PrincipalKey.Properties,
? foreignKey.Properties
: foreignKey.PrincipalKey.Properties,
makeNullable);
var innerKey = CreateKeyAccessExpression(
innerShapedQuery.ShaperExpression,
var innerKey = innerShapedQuery.ShaperExpression.CreateKeyAccessExpression(
navigation.IsDependentToPrincipal()
? navigation.ForeignKey.PrincipalKey.Properties
: navigation.ForeignKey.Properties,
? foreignKey.PrincipalKey.Properties
: foreignKey.Properties,
makeNullable);

var joinPredicate = _sqlTranslator.Translate(Expression.Equal(outerKey, innerKey));
Expand All @@ -1144,19 +1138,6 @@ private Expression Expand(Expression source, MemberIdentity member)

return innerShaper;
}

public static Expression CreateKeyAccessExpression(
Expression target, IReadOnlyList<IProperty> properties, bool makeNullable = false)
=> properties.Count == 1
? target.CreateEFPropertyExpression(properties[0], makeNullable)
: Expression.New(
AnonymousObject.AnonymousObjectCtor,
Expression.NewArrayInit(
typeof(object),
properties
.Select(p => Expression.Convert(target.CreateEFPropertyExpression(p, makeNullable), typeof(object)))
.Cast<Expression>()
.ToArray()));
}

private ShapedQueryExpression AggregateResultShaper(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,11 @@ protected override Expression VisitExtension(Expression extensionExpression)
}

private object GetProjectionIndex(ProjectionBindingExpression projectionBindingExpression)
{
return projectionBindingExpression.ProjectionMember != null
=> projectionBindingExpression.ProjectionMember != null
? ((ConstantExpression)_selectExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember)).Value
: (projectionBindingExpression.Index != null
? (object)projectionBindingExpression.Index
: projectionBindingExpression.IndexMap);
}

private static bool IsNullableProjection(ProjectionExpression projection)
=> !(projection.Expression is ColumnExpression column) || column.IsNullable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ private bool TryBindMember(Expression source, MemberIdentity member, out Express
var entityType = entityProjectionExpression.EntityType;
if (convertedType != null)
{
entityType = entityType.RootType().GetDerivedTypesInclusive()
entityType = entityType.GetRootType().GetDerivedTypesInclusive()
.FirstOrDefault(et => et.ClrType == convertedType);

if (entityType == null)
Expand Down
Loading

0 comments on commit 07e6609

Please sign in to comment.