public virtual void AddNavigationBinding(INavigation navigation, EntityShaperExpression entityShaper) { if (!EntityType.IsAssignableFrom(navigation.DeclaringEntityType) && !navigation.DeclaringEntityType.IsAssignableFrom(EntityType)) { throw new InvalidOperationException( $"Called EntityProjectionExpression.AddNavigationBinding() with incorrect INavigation. " + $"EntityType:{EntityType.DisplayName()}, Property:{navigation.Name}"); } _navigationExpressionsCache[navigation] = entityShaper; }
/// <summary> /// Adds a navigation binding for this entity projection when the target entity type of the navigation is owned or weak. /// </summary> /// <param name="navigation"> A navigation to add binding for. </param> /// <param name="entityShaper"> An entity shaper expression for the target type. </param> public virtual void AddNavigationBinding([NotNull] INavigation navigation, [NotNull] EntityShaperExpression entityShaper) { Check.NotNull(navigation, nameof(navigation)); Check.NotNull(entityShaper, nameof(entityShaper)); if (!EntityType.IsAssignableFrom(navigation.DeclaringEntityType) && !navigation.DeclaringEntityType.IsAssignableFrom(EntityType)) { throw new InvalidOperationException( RelationalStrings.UnableToBindMemberToEntityProjection("Navigation", navigation.Name, EntityType.DisplayName())); } _ownedNavigationMap[navigation] = entityShaper; }
public virtual void AddNavigationBinding([NotNull] INavigation navigation, [NotNull] EntityShaperExpression entityShaper) { Check.NotNull(navigation, nameof(navigation)); Check.NotNull(entityShaper, nameof(entityShaper)); if (!EntityType.IsAssignableFrom(navigation.DeclaringEntityType) && !navigation.DeclaringEntityType.IsAssignableFrom(EntityType)) { throw new InvalidOperationException( CoreStrings.EntityProjectionExpressionCalledWithIncorrectInterface( "AddNavigationBinding", "INavigation", EntityType.DisplayName(), navigation.Name)); } _navigationExpressionsCache[navigation] = entityShaper; }
private Expression Expand(Expression source, MemberIdentity member) { Type convertedType = null; if (source is UnaryExpression unaryExpression && unaryExpression.NodeType == ExpressionType.Convert) { source = unaryExpression.Operand; if (unaryExpression.Type != typeof(object)) { convertedType = unaryExpression.Type; } } if (source is EntityShaperExpression entityShaperExpression) { var entityType = entityShaperExpression.EntityType; if (convertedType != null) { entityType = entityType.RootType().GetDerivedTypesInclusive() .FirstOrDefault(et => et.ClrType == convertedType); if (entityType == null) { return(null); } } var navigation = member.MemberInfo != null ? entityType.FindNavigation(member.MemberInfo) : entityType.FindNavigation(member.Name); if (navigation != null && navigation.ForeignKey.IsOwnership) { if (navigation.IsCollection()) { return(CreateShapedQueryExpression( navigation.GetTargetType(), _sqlExpressionFactory.Select(navigation.GetTargetType()))); } var entityProjectionExpression = (EntityProjectionExpression) (entityShaperExpression.ValueBufferExpression is ProjectionBindingExpression projectionBindingExpression ? _selectExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember) : entityShaperExpression.ValueBufferExpression); var innerShaper = entityProjectionExpression.BindNavigation(navigation); if (innerShaper == null) { var targetEntityType = navigation.GetTargetType(); var innerSelectExpression = _sqlExpressionFactory.Select(targetEntityType); var innerShapedQuery = CreateShapedQueryExpression(targetEntityType, innerSelectExpression); var makeNullable = navigation.ForeignKey.PrincipalKey.Properties .Concat(navigation.ForeignKey.Properties) .Select(p => p.ClrType) .Any(t => t.IsNullableType()); var outerKey = CreateKeyAccessExpression( entityShaperExpression, navigation.ForeignKey.PrincipalKey.Properties, makeNullable); var innerKey = CreateKeyAccessExpression( innerShapedQuery.ShaperExpression, navigation.ForeignKey.Properties, makeNullable); var joinPredicate = _sqlTranslator.Translate(Expression.Equal(outerKey, innerKey)); _selectExpression.AddLeftJoin(innerSelectExpression, joinPredicate, null); var leftJoinTable = ((LeftJoinExpression)_selectExpression.Tables.Last()).Table; innerShaper = new EntityShaperExpression(targetEntityType, new EntityProjectionExpression(targetEntityType, leftJoinTable, true), true); entityProjectionExpression.AddNavigationBinding(navigation, innerShaper); } return(innerShaper); } } return(null); }