From 174f7babd1b1cc142cabf3e2105d08fdca592ca5 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Thu, 28 Aug 2025 17:46:58 +0200 Subject: [PATCH] Rename "relationship" to "structural property" --- .../Query/CollectionResultExpression.cs | 20 +-- ...ionalProjectionBindingExpressionVisitor.cs | 4 +- .../Query/JsonQueryExpression.cs | 8 +- ...yableMethodTranslatingExpressionVisitor.cs | 2 +- ...ocessingExpressionVisitor.ClientMethods.cs | 4 +- ...sitor.ShaperProcessingExpressionVisitor.cs | 132 +++++++++--------- ...ingExpressionVisitor.StructuralEquality.cs | 8 +- ...lationalSqlTranslatingExpressionVisitor.cs | 2 +- .../SqlExpressions/SelectExpression.Helper.cs | 2 +- .../Internal/ClrCollectionAccessorFactory.cs | 52 +++---- .../LiftableConstantExpressionHelpers.cs | 26 ++-- 11 files changed, 130 insertions(+), 130 deletions(-) diff --git a/src/EFCore.Relational/Query/CollectionResultExpression.cs b/src/EFCore.Relational/Query/CollectionResultExpression.cs index 17aaee5be67..d866c5f1111 100644 --- a/src/EFCore.Relational/Query/CollectionResultExpression.cs +++ b/src/EFCore.Relational/Query/CollectionResultExpression.cs @@ -14,11 +14,11 @@ namespace Microsoft.EntityFrameworkCore.Query; /// /// /// Represents the server-side query expression for the collection. -/// A navigation associated with this collection, if any. -/// The clr type of individual elements in the collection. +/// The navigation or complex property associated with the collection, if any. +/// The .NET type of individual elements in the collection. public class CollectionResultExpression( Expression queryExpression, - IPropertyBase? relationship, + IPropertyBase? structuralProperty, Type elementType) : Expression, IPrintableExpression { @@ -28,12 +28,12 @@ public class CollectionResultExpression( public virtual Expression QueryExpression { get; } = queryExpression; /// - /// The relationship associated with the collection, if any. + /// The navigation or complex property associated with the collection, if any. /// - public virtual IPropertyBase? Relationship { get; } = relationship; + public virtual IPropertyBase? StructuralProperty { get; } = structuralProperty; /// - /// The clr type of elements of the collection. + /// The .NET type of elements of the collection. /// public virtual Type ElementType { get; } = elementType; @@ -58,7 +58,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) public virtual CollectionResultExpression Update(Expression queryExpression) => queryExpression == QueryExpression ? this - : new CollectionResultExpression(queryExpression, Relationship, ElementType); + : new CollectionResultExpression(queryExpression, StructuralProperty, ElementType); /// public virtual void Print(ExpressionPrinter expressionPrinter) @@ -70,9 +70,9 @@ public virtual void Print(ExpressionPrinter expressionPrinter) expressionPrinter.Visit(QueryExpression); expressionPrinter.AppendLine(); - if (Relationship is not null) + if (StructuralProperty is not null) { - expressionPrinter.Append("Relationship:").AppendLine(Relationship.ToString()!); + expressionPrinter.Append("Structural Property:").AppendLine(StructuralProperty.ToString()!); } expressionPrinter.Append("ElementType:").AppendLine(ElementType.ShortDisplayName()); @@ -88,6 +88,6 @@ public virtual void Print(ExpressionPrinter expressionPrinter) /// /// The navigation if associated with the collection. /// - [Obsolete("Use Relationship instead.", error: true)] + [Obsolete("Use StructuralProperty instead.", error: true)] public virtual INavigationBase? Navigation { get; } } diff --git a/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs index a90b94ed6fe..3614afaf165 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs @@ -198,7 +198,7 @@ public virtual Expression Translate(SelectExpression selectExpression, Expressio // expression.Type here will be List return new CollectionResultExpression( new ProjectionBindingExpression(_selectExpression, _clientProjections.Count - 1, expression.Type), - relationship: null, + structuralProperty: null, methodCallExpression.Method.GetGenericArguments()[0]); } } @@ -219,7 +219,7 @@ public virtual Expression Translate(SelectExpression selectExpression, Expressio _selectExpression, _clientProjections.Count - 1, type); return subquery.ResultCardinality == ResultCardinality.Enumerable ? new CollectionResultExpression( - projectionBindingExpression, relationship: null, subquery.ShaperExpression.Type) + projectionBindingExpression, structuralProperty: null, subquery.ShaperExpression.Type) : projectionBindingExpression; } } diff --git a/src/EFCore.Relational/Query/JsonQueryExpression.cs b/src/EFCore.Relational/Query/JsonQueryExpression.cs index d9346a7f292..b0168a5c1f1 100644 --- a/src/EFCore.Relational/Query/JsonQueryExpression.cs +++ b/src/EFCore.Relational/Query/JsonQueryExpression.cs @@ -146,13 +146,13 @@ public virtual SqlExpression BindProperty(IProperty property) } /// - /// Binds a relationship with this JSON query expression to get the SQL representation. + /// Binds a navigation or complex property with this JSON query expression to get the SQL representation. /// - /// The navigation or complex property to bind. + /// The navigation or complex property to bind. /// An JSON query expression for the target entity or complex type. - public virtual JsonQueryExpression BindRelationship(IPropertyBase relationship) + public virtual JsonQueryExpression BindStructuralProperty(IPropertyBase structuralProperty) { - switch (relationship) + switch (structuralProperty) { case INavigation navigation: { diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs index cd1840a4d9d..03b510c1048 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs @@ -1814,7 +1814,7 @@ Expression ExpandOwnedNavigation(INavigation navigation) if (TryGetJsonQueryExpression(shaper, out var jsonQueryExpression)) { - var newJsonQueryExpression = jsonQueryExpression.BindRelationship(navigation); + var newJsonQueryExpression = jsonQueryExpression.BindStructuralProperty(navigation); Debug.Assert(!navigation.IsOnDependent, "JSON navigations should always be from principal do dependent"); diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs index e70acb55192..fb562be9250 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs @@ -1055,7 +1055,7 @@ static async Task InitializeReaderAsync( QueryContext queryContext, object[]? keyPropertyValues, JsonReaderData? jsonReaderData, - IPropertyBase relationship, + IPropertyBase structuralProperty, Func innerShaper) where TEntity : class { @@ -1076,7 +1076,7 @@ static async Task InitializeReaderAsync( throw new InvalidOperationException(CoreStrings.JsonReaderInvalidTokenType(tokenType.ToString())); } - var collectionAccessor = relationship.GetCollectionAccessor(); + var collectionAccessor = structuralProperty.GetCollectionAccessor(); var result = (TResult)collectionAccessor!.Create(); object[]? newKeyPropertyValues = null; diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs index e420c1586fe..b2571842ed6 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs @@ -633,7 +633,7 @@ protected override Expression VisitExtension(Expression extensionExpression) jsonReaderDataVariable, keyValuesParameter, containerEntityExpression: null, - relationship: null); + structuralProperty: null); var visitedShaperResult = Visit(shaperResult); var visitedShaperResultParameter = Parameter(visitedShaperResult.Type); @@ -761,14 +761,14 @@ protected override Expression VisitExtension(Expression extensionExpression) case CollectionResultExpression { QueryExpression: ProjectionBindingExpression projectionBindingExpression, - Relationship: { } relationship, + StructuralProperty: { } structuralProperty, } collectionResult when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonProjectionInfo: { - var relatedStructuralType = relationship switch + ITypeBase relatedStructuralType = structuralProperty switch { - IComplexProperty complexProperty => (ITypeBase)complexProperty.ComplexType, - INavigation navigation => navigation.TargetEntityType, + IComplexProperty p => p.ComplexType, + INavigation n => n.TargetEntityType, _ => throw new UnreachableException() }; @@ -787,12 +787,12 @@ when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonP var shaperResult = CreateJsonShapers( relatedStructuralType, - relationship.ClrType, + structuralProperty.ClrType, nullable: true, jsonReaderDataVariable, keyValuesParameter, containerEntityExpression: null, - relationship); + structuralProperty); var visitedShaperResult = Visit(shaperResult); @@ -947,7 +947,7 @@ when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonP outerIdentifierLambdaCompiled, _parentVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant( navigation, - LiftableConstantExpressionHelpers.BuildRelationshipAccessLambda(navigation), + LiftableConstantExpressionHelpers.BuildStructuralPropertyAccessLambda(navigation), navigation.Name + "Navigation", typeof(INavigationBase)), navigation.IsShadowProperty() @@ -1011,7 +1011,7 @@ when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonP innerShaper, _parentVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant( inverseNavigation, - LiftableConstantExpressionHelpers.BuildRelationshipAccessLambda(inverseNavigation), + LiftableConstantExpressionHelpers.BuildStructuralPropertyAccessLambda(inverseNavigation), (inverseNavigation?.Name ?? "null") + "InverseNavigation", typeof(INavigationBase)), GenerateFixup(includingEntityClrType, relatedEntityClrType, navigation, inverseNavigation), @@ -1085,7 +1085,7 @@ when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonP parentIdentifierLambdaCompiled, _parentVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant( navigation, - LiftableConstantExpressionHelpers.BuildRelationshipAccessLambda(navigation), + LiftableConstantExpressionHelpers.BuildStructuralPropertyAccessLambda(navigation), navigation.Name + "Navigation", typeof(INavigationBase)), _parentVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant( @@ -1133,7 +1133,7 @@ when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonP : typeof(Action)), _parentVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant( inverseNavigation, - LiftableConstantExpressionHelpers.BuildRelationshipAccessLambda(inverseNavigation), + LiftableConstantExpressionHelpers.BuildStructuralPropertyAccessLambda(inverseNavigation), (inverseNavigation?.Name ?? "null") + "InverseNavigation", typeof(INavigationBase)), GenerateFixup(includingEntityClrType, relatedEntityClrType, navigation, inverseNavigation), @@ -1191,12 +1191,12 @@ when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonP navigationExpression, _parentVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant( navigation, - LiftableConstantExpressionHelpers.BuildRelationshipAccessLambda(navigation), + LiftableConstantExpressionHelpers.BuildStructuralPropertyAccessLambda(navigation), navigation.Name + "Navigation", typeof(INavigation)), _parentVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant( inverseNavigation, - LiftableConstantExpressionHelpers.BuildRelationshipAccessLambda(inverseNavigation), + LiftableConstantExpressionHelpers.BuildStructuralPropertyAccessLambda(inverseNavigation), (inverseNavigation?.Name ?? "null") + "InverseNavigation", typeof(INavigation)), GenerateFixup(includingType, relatedEntityType, navigation, inverseNavigation), @@ -1574,7 +1574,7 @@ private Expression CreateJsonShapers( ParameterExpression jsonReaderDataParameter, Expression? keyValuesParameter, Expression? containerEntityExpression, - IPropertyBase? relationship) + IPropertyBase? structuralProperty) { var jsonReaderDataShaperLambdaParameter = Parameter(typeof(JsonReaderData)); // TODO: Use ISnapshot instead #26544 @@ -1600,32 +1600,32 @@ private Expression CreateJsonShapers( var innerFixupMap = new Dictionary(); var trackingInnerFixupMap = new Dictionary(); - // Go over all relationships (complex properties and navigations - if we're an (owned) entity), which represent JSON + // Go over all structural properties (complex properties and navigations - if we're an (owned) entity), which represent JSON // nested types; generate shapers and fixup to wire the materialized related instance into the parent's property. // Note that we need to build entity shapers and fixup separately; we don't know the order in which data comes, so // we need to read through everything before we can do fixup safely - IEnumerable nestedRelationships = structuralType.GetComplexProperties(); + IEnumerable nestedStructuralProperties = structuralType.GetComplexProperties(); if (structuralType is IEntityType entityType) { - nestedRelationships = nestedRelationships.Concat( + nestedStructuralProperties = nestedStructuralProperties.Concat( entityType.GetNavigations() .Where(n => n.TargetEntityType.IsMappedToJson() && n.ForeignKey.IsOwnership && n == n.ForeignKey.PrincipalToDependent)); } - foreach (var nestedRelationship in nestedRelationships) + foreach (var nestedStructuralProperty in nestedStructuralProperties) { Check.DebugAssert( - nestedRelationship is not INavigation ownedNavigation || !ownedNavigation.IsOnDependent, + nestedStructuralProperty is not INavigation ownedNavigation || !ownedNavigation.IsOnDependent, "JSON navigations should always be from principal do dependent"); Check.DebugAssert( - nestedRelationship is not IComplexProperty { ComplexType: var complexType } || complexType.IsMappedToJson(), + nestedStructuralProperty is not IComplexProperty { ComplexType: var complexType } || complexType.IsMappedToJson(), "Non-JSON complex type within JSON complex type"); - var (relatedStructuralType, inverseNavigation, isRelationshipNullable) = nestedRelationship switch + var (relatedStructuralType, inverseNavigation, isStructuralPropertyNullable) = nestedStructuralProperty switch { INavigation n => ((ITypeBase)n.TargetEntityType, n.Inverse, !n.ForeignKey.IsRequiredDependent), IComplexProperty cp => (cp.ComplexType, null, cp.IsNullable), @@ -1635,28 +1635,28 @@ private Expression CreateJsonShapers( var innerShaper = CreateJsonShapers( relatedStructuralType, - nestedRelationship.ClrType, - nullable || isRelationshipNullable, + nestedStructuralProperty.ClrType, + nullable || isStructuralPropertyNullable, jsonReaderDataShaperLambdaParameter, keyValuesShaperLambdaParameter, containerEntityExpression: null, - nestedRelationship); + nestedStructuralProperty); var navigationJsonPropertyName = relatedStructuralType.GetJsonPropertyName()!; innerShapersMap[navigationJsonPropertyName] = innerShaper; - if (nestedRelationship.IsCollection) + if (nestedStructuralProperty.IsCollection) { var shaperEntityParameter = Parameter(structuralType.ClrType); - var ownedNavigationType = nestedRelationship.GetMemberInfo(forMaterialization: true, forSet: true).GetMemberType(); + var ownedNavigationType = nestedStructuralProperty.GetMemberInfo(forMaterialization: true, forSet: true).GetMemberType(); var shaperCollectionParameter = Parameter(ownedNavigationType); var expressions = new List(); var expressionsForTracking = new List(); - if (!nestedRelationship.IsShadowProperty()) + if (!nestedStructuralProperty.IsShadowProperty()) { expressions.Add( - shaperEntityParameter.MakeMemberAccess(nestedRelationship.GetMemberInfo(forMaterialization: true, forSet: true)) + shaperEntityParameter.MakeMemberAccess(nestedStructuralProperty.GetMemberInfo(forMaterialization: true, forSet: true)) .Assign(shaperCollectionParameter)); expressionsForTracking.Add( @@ -1668,7 +1668,7 @@ private Expression CreateJsonShapers( typeof(ShaperProcessingExpressionVisitor).GetMethod(nameof(Any))!, shaperCollectionParameter))), shaperEntityParameter - .MakeMemberAccess(nestedRelationship.GetMemberInfo(forMaterialization: true, forSet: true)) + .MakeMemberAccess(nestedStructuralProperty.GetMemberInfo(forMaterialization: true, forSet: true)) .Assign(shaperCollectionParameter))); } @@ -1717,8 +1717,8 @@ private Expression CreateJsonShapers( { var fixup = GenerateReferenceFixupForJson( structuralType.ClrType, - nestedRelationship.ClrType, - nestedRelationship, + nestedStructuralProperty.ClrType, + nestedStructuralProperty, inverseNavigation); // With tracking queries, the change tracker performs entity fixup, so we only need to handle fixup in the shaper for @@ -1765,10 +1765,10 @@ private Expression CreateJsonShapers( // (since we are guaranteed that the parent already exists) - for nested JSON materialization we need to do fixup at the end // because we are streaming the data and don't know if we get the parent json object before the child // (in case parent ctor takes some parameters and they are read as last thing in the JSON) - Check.DebugAssert(relationship is not null, "relationship shouldn't be null when including."); + Check.DebugAssert(structuralProperty is not null, "Structural properties shouldn't be null when including."); - var declaringClrType = relationship.DeclaringType.ClrType; - var relatedClrType = relationship switch + var declaringClrType = structuralProperty.DeclaringType.ClrType; + var relatedClrType = structuralProperty switch { INavigation n => n.TargetEntityType.ClrType, IComplexProperty cp => cp.ComplexType.ClrType, @@ -1776,17 +1776,17 @@ private Expression CreateJsonShapers( }; var fixup = GenerateFixup( - relationship.DeclaringType.ClrType, + structuralProperty.DeclaringType.ClrType, relatedClrType, - relationship, - relationship is INavigation navigation ? navigation.Inverse : null); + structuralProperty, + structuralProperty is INavigation navigation ? navigation.Inverse : null); // inheritance scenario - navigation/complex property defined on derived var includingEntityExpression = containerEntityExpression.Type != declaringClrType ? Convert(containerEntityExpression, declaringClrType) : containerEntityExpression; - if (relationship.IsCollection) + if (structuralProperty.IsCollection) { var includeJsonEntityCollectionMethodCall = Call( @@ -1796,7 +1796,7 @@ private Expression CreateJsonShapers( jsonReaderDataParameter, includingEntityExpression, shaperLambda, - GetOrCreateCollectionObjectLambda(declaringClrType, relationship), + GetOrCreateCollectionObjectLambda(declaringClrType, structuralProperty), fixup, // Perform fixup only for non-tracking queries - for tracking queries the change tracker does fixup. // Note that for complex JSON types we also perform fixup, even for tracking queries. @@ -1829,13 +1829,13 @@ private Expression CreateJsonShapers( includeJsonEntityReferenceMethodCall); } - if (relationship is { IsCollection: true }) + if (structuralProperty is { IsCollection: true }) { - var collectionClrType = relationship.GetMemberInfo(forMaterialization: true, forSet: true).GetMemberType(); + var collectionClrType = structuralProperty.GetMemberInfo(forMaterialization: true, forSet: true).GetMemberType(); var materializeJsonEntityCollectionMethodCall = Call( MaterializeJsonEntityCollectionMethodInfo.MakeGenericMethod( - relationship switch + structuralProperty switch { INavigation n => n.TargetEntityType.ClrType, IComplexProperty cp => cp.ComplexType.ClrType, @@ -1846,9 +1846,9 @@ private Expression CreateJsonShapers( keyValuesParameter, jsonReaderDataParameter, _parentVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant( - relationship, - LiftableConstantExpressionHelpers.BuildRelationshipAccessLambda(relationship), - relationship.Name + "Relationship", + structuralProperty, + LiftableConstantExpressionHelpers.BuildStructuralPropertyAccessLambda(structuralProperty), + structuralProperty.Name + "StructuralProperty", typeof(IPropertyBase)), shaperLambda); @@ -1862,7 +1862,7 @@ private Expression CreateJsonShapers( { // We need to project out a nullable value type. Note that the shaperLambda that we pass itself always returns a // non-nullable value (the null checks are outside of it.)) - Check.DebugAssert(nullable, "On non-nullable relationship but the relationship's ClrType is Nullable"); + Check.DebugAssert(nullable, "On non-nullable structural property but the property's ClrType is Nullable"); Check.DebugAssert(underlyingType == structuralType.ClrType); method = MaterializeJsonNullableValueStructuralTypeMethodInfo.MakeGenericMethod(structuralType.ClrType); @@ -2549,7 +2549,7 @@ internal void ProcessTopLevelComplexJsonProperties( jsonReaderDataVariable, keyValuesParameter: null, // For owned entities only containerEntityExpression: instanceVariable, - relationship: complexProperty); + structuralProperty: complexProperty); var visitedShaperResult = Visit(shaperResult); expressions.Add(visitedShaperResult); @@ -2787,19 +2787,19 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp private LambdaExpression GenerateFixup( Type structuralClrType, Type relatedStructuralClrType, - IPropertyBase relationship, + IPropertyBase structuralProperty, INavigationBase? inverseNavigation) { var entityParameter = Parameter(structuralClrType); var relatedEntityParameter = Parameter(relatedStructuralClrType); var expressions = new List(); - if (!relationship.IsShadowProperty()) + if (!structuralProperty.IsShadowProperty()) { expressions.Add( - relationship.IsCollection - ? AddToCollectionRelationship(entityParameter, relatedEntityParameter, relationship) - : AssignStructuralProperty(entityParameter, relatedEntityParameter, relationship)); + structuralProperty.IsCollection + ? AddToCollectionStructuralProperty(entityParameter, relatedEntityParameter, structuralProperty) + : AssignStructuralProperty(entityParameter, relatedEntityParameter, structuralProperty)); } if (inverseNavigation != null @@ -2807,7 +2807,7 @@ private LambdaExpression GenerateFixup( { expressions.Add( inverseNavigation.IsCollection - ? AddToCollectionRelationship(relatedEntityParameter, entityParameter, inverseNavigation) + ? AddToCollectionStructuralProperty(relatedEntityParameter, entityParameter, inverseNavigation) : AssignStructuralProperty(relatedEntityParameter, entityParameter, inverseNavigation)); } @@ -2817,20 +2817,20 @@ private LambdaExpression GenerateFixup( private static LambdaExpression GenerateReferenceFixupForJson( Type clrType, Type relatedClrType, - IPropertyBase relationship, + IPropertyBase structuralProperty, INavigationBase? inverseNavigation) { var entityParameter = Parameter(clrType); var relatedEntityParameter = Parameter(relatedClrType); var expressions = new List(); - if (!relationship.IsShadowProperty()) + if (!structuralProperty.IsShadowProperty()) { expressions.Add( AssignStructuralProperty( entityParameter, relatedEntityParameter, - relationship)); + structuralProperty)); } if (inverseNavigation != null @@ -2880,7 +2880,7 @@ private static Expression AssignStructuralProperty( return structuralType.MakeMemberAccess(setter).Assign(assignee); } - private Expression GetOrCreateCollectionObjectLambda(Type entityType, IPropertyBase relationship) + private Expression GetOrCreateCollectionObjectLambda(Type entityType, IPropertyBase structuralProperty) { var prm = Parameter(entityType); @@ -2889,9 +2889,9 @@ private Expression GetOrCreateCollectionObjectLambda(Type entityType, IPropertyB typeof(void), Call( _parentVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant( - relationship.GetCollectionAccessor(), - LiftableConstantExpressionHelpers.BuildClrCollectionAccessorLambda(relationship), - relationship.Name + "RelationshipCollectionAccessor", + structuralProperty.GetCollectionAccessor(), + LiftableConstantExpressionHelpers.BuildClrCollectionAccessorLambda(structuralProperty), + structuralProperty.Name + "StructuralPropertyCollectionAccessor", typeof(IClrCollectionAccessor)), CollectionAccessorGetOrCreateMethodInfo, prm, @@ -2899,15 +2899,15 @@ private Expression GetOrCreateCollectionObjectLambda(Type entityType, IPropertyB prm); } - private Expression AddToCollectionRelationship( + private Expression AddToCollectionStructuralProperty( ParameterExpression entity, ParameterExpression relatedEntity, - IPropertyBase relationship) + IPropertyBase structuralProperty) => Call( _parentVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant( - relationship.GetCollectionAccessor(), - LiftableConstantExpressionHelpers.BuildClrCollectionAccessorLambda(relationship), - relationship.Name + "RelationshipCollectionAccessor", + structuralProperty.GetCollectionAccessor(), + LiftableConstantExpressionHelpers.BuildClrCollectionAccessorLambda(structuralProperty), + structuralProperty.Name + "StructuralPropertyCollectionAccessor", typeof(IClrCollectionAccessor)), CollectionAccessorAddMethodInfo, entity, @@ -3488,7 +3488,7 @@ protected override Expression VisitExtension(Expression extensionExpression) nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution))); case JsonProjectionInfo jsonCollectionProjectionInfo - when collectionResultExpression.Relationship is INavigation navigation: + when collectionResultExpression.StructuralProperty is INavigation navigation: { var jsonEntityType = navigation.TargetEntityType; diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.StructuralEquality.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.StructuralEquality.cs index 75d0c415c1d..c737208219b 100644 --- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.StructuralEquality.cs +++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.StructuralEquality.cs @@ -110,8 +110,8 @@ private bool TryRewriteStructuralTypeEquality( case (_, StructuralTypeReferenceExpression { StructuralType: IComplexType }): return TryRewriteComplexTypeEquality(collection: false, out result); - case (CollectionResultExpression { Relationship: IComplexProperty }, _): - case (_, CollectionResultExpression { Relationship: IComplexProperty }): + case (CollectionResultExpression { StructuralProperty: IComplexProperty }, _): + case (_, CollectionResultExpression { StructuralProperty: IComplexProperty }): return TryRewriteComplexTypeEquality(collection: true, out result); default: @@ -281,14 +281,14 @@ bool TryRewriteComplexTypeEquality(bool collection, [NotNullWhen(true)] out SqlE var leftComplexType = left switch { StructuralTypeReferenceExpression { StructuralType: IComplexType t } => t, - CollectionResultExpression { Relationship: IComplexProperty { ComplexType: var t } } => t, + CollectionResultExpression { StructuralProperty: IComplexProperty { ComplexType: var t } } => t, _ => null }; var rightComplexType = right switch { StructuralTypeReferenceExpression { StructuralType: IComplexType t } => t, - CollectionResultExpression { Relationship: IComplexProperty { ComplexType: var t } } => t, + CollectionResultExpression { StructuralProperty: IComplexProperty { ComplexType: var t } } => t, _ => null }; diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs index 814adf1e349..c68f69f514c 100644 --- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs @@ -1379,7 +1379,7 @@ private Expression BindComplexProperty(StructuralTypeReferenceExpression typeRef }; case JsonQueryExpression jsonQuery: - var nestedJsonQuery = jsonQuery.BindRelationship(complexProperty); + var nestedJsonQuery = jsonQuery.BindStructuralProperty(complexProperty); return complexProperty.IsCollection ? new CollectionResultExpression( diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs index af41777a850..04f2efa9bcc 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs @@ -283,7 +283,7 @@ protected override Expression VisitExtension(Expression expression) QueryExpression: ProjectionBindingExpression innerProjectionBindingExpression } collectionResultExpression: { - var navigation = collectionResultExpression.Relationship switch + var navigation = collectionResultExpression.StructuralProperty switch { INavigationBase n => n, null => null, diff --git a/src/EFCore/Metadata/Internal/ClrCollectionAccessorFactory.cs b/src/EFCore/Metadata/Internal/ClrCollectionAccessorFactory.cs index d162e49a949..a828b5a2faf 100644 --- a/src/EFCore/Metadata/Internal/ClrCollectionAccessorFactory.cs +++ b/src/EFCore/Metadata/Internal/ClrCollectionAccessorFactory.cs @@ -44,20 +44,20 @@ private ClrCollectionAccessorFactory() /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual IClrCollectionAccessor? Create(IPropertyBase relationship) + public virtual IClrCollectionAccessor? Create(IPropertyBase structuralProperty) { - if (!relationship.IsCollection) + if (!structuralProperty.IsCollection) { return null; } // ReSharper disable once SuspiciousTypeConversion.Global - if (relationship is IClrCollectionAccessor accessor) + if (structuralProperty is IClrCollectionAccessor accessor) { return accessor; } - var targetType = relationship switch + var targetType = structuralProperty switch { INavigationBase navigation => (ITypeBase)navigation.TargetEntityType, IComplexProperty complexProperty => complexProperty.ComplexType, @@ -70,9 +70,9 @@ private ClrCollectionAccessorFactory() return null; } - var memberInfo = GetMostDerivedMemberInfo(relationship); - var propertyType = relationship.IsIndexerProperty() || relationship.IsShadowProperty() - ? relationship.ClrType + var memberInfo = GetMostDerivedMemberInfo(structuralProperty); + var propertyType = structuralProperty.IsIndexerProperty() || structuralProperty.IsShadowProperty() + ? structuralProperty.ClrType : memberInfo!.GetMemberType(); var elementType = propertyType.TryGetElementType(typeof(IEnumerable<>)); @@ -80,8 +80,8 @@ private ClrCollectionAccessorFactory() { throw new InvalidOperationException( CoreStrings.NavigationBadType( // TODO: Update - relationship.Name, - relationship.DeclaringType.DisplayName(), + structuralProperty.Name, + structuralProperty.DeclaringType.DisplayName(), propertyType.ShortDisplayName(), targetType.DisplayName())); } @@ -90,17 +90,17 @@ private ClrCollectionAccessorFactory() { throw new InvalidOperationException( CoreStrings.NavigationArray( - relationship.Name, - relationship.DeclaringType.DisplayName(), + structuralProperty.Name, + structuralProperty.DeclaringType.DisplayName(), propertyType.ShortDisplayName())); } var boundMethod = GenericCreate.MakeGenericMethod( - memberInfo?.DeclaringType ?? relationship.DeclaringType.ClrType, propertyType, elementType); + memberInfo?.DeclaringType ?? structuralProperty.DeclaringType.ClrType, propertyType, elementType); try { - return (IClrCollectionAccessor?)boundMethod.Invoke(null, [relationship]); + return (IClrCollectionAccessor?)boundMethod.Invoke(null, [structuralProperty]); } catch (TargetInvocationException invocationException) { @@ -109,12 +109,12 @@ private ClrCollectionAccessorFactory() } [UsedImplicitly] - private static IClrCollectionAccessor CreateGeneric(IPropertyBase relationship) + private static IClrCollectionAccessor CreateGeneric(IPropertyBase structuralProperty) where TCollection : class, IEnumerable where TElement : class { CreateExpressions( - relationship, + structuralProperty, out var getCollection, out var setCollection, out var setCollectionForMaterialization, @@ -122,8 +122,8 @@ private static IClrCollectionAccessor CreateGeneric( - relationship.Name, - relationship.IsShadowProperty(), + structuralProperty.Name, + structuralProperty.IsShadowProperty(), getCollection?.Compile(), setCollection?.Compile(), setCollectionForMaterialization?.Compile(), @@ -180,7 +180,7 @@ private static readonly MethodInfo GenericCreateExpressions [UsedImplicitly] private static void CreateExpressions( - IPropertyBase relationship, + IPropertyBase structuralProperty, out Expression>? getCollection, out Expression>? setCollection, out Expression>? setCollectionForMaterialization, @@ -198,11 +198,11 @@ private static void CreateExpressions( var entityParameter = Expression.Parameter(typeof(TStructural), "entity"); var valueParameter = Expression.Parameter(typeof(TCollection), "collection"); - if (!relationship.IsShadowProperty()) + if (!structuralProperty.IsShadowProperty()) { - var memberInfoForRead = relationship.GetMemberInfo(forMaterialization: false, forSet: false); - relationship.TryGetMemberInfo(forMaterialization: false, forSet: true, out var memberInfoForWrite, out _); - relationship.TryGetMemberInfo(forMaterialization: true, forSet: true, out var memberInfoForMaterialization, out _); + var memberInfoForRead = structuralProperty.GetMemberInfo(forMaterialization: false, forSet: false); + structuralProperty.TryGetMemberInfo(forMaterialization: false, forSet: true, out var memberInfoForWrite, out _); + structuralProperty.TryGetMemberInfo(forMaterialization: true, forSet: true, out var memberInfoForMaterialization, out _); var memberAccessForRead = (Expression)Expression.MakeMemberAccess(entityParameter, memberInfoForRead); if (memberAccessForRead.Type != typeof(TCollection)) { @@ -227,7 +227,7 @@ private static void CreateExpressions( var concreteType = CollectionTypeFactory.Instance.TryFindTypeToInstantiate( typeof(TStructural), typeof(TCollection), - relationship.DeclaringType.Model[CoreAnnotationNames.FullChangeTrackingNotificationsRequired] != null); + structuralProperty.DeclaringType.Model[CoreAnnotationNames.FullChangeTrackingNotificationsRequired] != null); if (concreteType != null) { var isHashSet = concreteType.IsGenericType && concreteType.GetGenericTypeDefinition() == typeof(HashSet<>); @@ -273,10 +273,10 @@ static Expression> CreateSetterDelegate( valueParameter1); } - private static MemberInfo? GetMostDerivedMemberInfo(IPropertyBase relationship) + private static MemberInfo? GetMostDerivedMemberInfo(IPropertyBase structuralProperty) { - var propertyInfo = relationship.PropertyInfo; - var fieldInfo = relationship.FieldInfo; + var propertyInfo = structuralProperty.PropertyInfo; + var fieldInfo = structuralProperty.FieldInfo; return fieldInfo == null ? propertyInfo diff --git a/src/EFCore/Query/LiftableConstantExpressionHelpers.cs b/src/EFCore/Query/LiftableConstantExpressionHelpers.cs index 79e51e950d3..2770e9f2d7a 100644 --- a/src/EFCore/Query/LiftableConstantExpressionHelpers.cs +++ b/src/EFCore/Query/LiftableConstantExpressionHelpers.cs @@ -200,19 +200,19 @@ public static Expression> Buil /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static Expression BuildRelationshipAccess(IPropertyBase? relationship, ParameterExpression liftableConstantContextParameter) + public static Expression BuildStructuralPropertyAccess(IPropertyBase? structuralProperty, ParameterExpression liftableConstantContextParameter) { - if (relationship is null) + if (structuralProperty is null) { return Default(typeof(INavigationBase)); } - var declaringType = relationship.DeclaringType; + var declaringType = structuralProperty.DeclaringType; var declaringTypeExpression = BuildMemberAccessForEntityOrComplexType(declaringType, liftableConstantContextParameter); var result = Call( declaringTypeExpression, - relationship switch + structuralProperty switch { ISkipNavigation => EntityTypeFindSkipNavigationMethod, INavigation => EntityTypeFindNavigationMethod, @@ -220,7 +220,7 @@ public static Expression BuildRelationshipAccess(IPropertyBase? relationship, Pa _ => throw new UnreachableException() }, - Constant(relationship.Name)); + Constant(structuralProperty.Name)); return result; } @@ -231,10 +231,10 @@ public static Expression BuildRelationshipAccess(IPropertyBase? relationship, Pa /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static Expression> BuildRelationshipAccessLambda(IPropertyBase? relationship) + public static Expression> BuildStructuralPropertyAccessLambda(IPropertyBase? structuralProperty) { var prm = Parameter(typeof(MaterializerLiftableConstantContext)); - var body = BuildRelationshipAccess(relationship, prm); + var body = BuildStructuralPropertyAccess(structuralProperty, prm); return Lambda>(body, prm); } @@ -245,15 +245,15 @@ public static Expression> Buil /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static Expression BuildClrCollectionAccessor(IPropertyBase? relationship, ParameterExpression liftableConstantContextParameter) + public static Expression BuildClrCollectionAccessor(IPropertyBase? structuralProperty, ParameterExpression liftableConstantContextParameter) { - if (relationship is null) + if (structuralProperty is null) { return Default(typeof(IClrCollectionAccessor)); } - var relationshipAccessExpression = BuildRelationshipAccess(relationship, liftableConstantContextParameter); - var result = Call(relationshipAccessExpression, PropertyBaseClrCollectionAccessorMethod); + var structuralPropertyAccessExpression = BuildStructuralPropertyAccess(structuralProperty, liftableConstantContextParameter); + var result = Call(structuralPropertyAccessExpression, PropertyBaseClrCollectionAccessorMethod); return result; } @@ -265,10 +265,10 @@ public static Expression BuildClrCollectionAccessor(IPropertyBase? relationship, /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public static Expression> BuildClrCollectionAccessorLambda( - IPropertyBase? relationship) + IPropertyBase? structuralProperty) { var prm = Parameter(typeof(MaterializerLiftableConstantContext)); - var body = BuildClrCollectionAccessor(relationship, prm); + var body = BuildClrCollectionAccessor(structuralProperty, prm); return Lambda>(body, prm); }