private (NavigationExpansionExpression navigationExpression, Expression nullKeyExpression) CreateNullComparisonArguments(
            NavigationBindingExpression navigationBindingExpression,
            NavigationExpansionExpression navigationExpansionExpression)
        {
            var navigationKeyAccessExpression = NavigationExpansionHelpers.CreateKeyAccessExpression(
                navigationBindingExpression,
                new[] { navigationBindingExpression.EntityType.FindPrimaryKey().Properties.First() },
                addNullCheck: true);

            var nullKeyExpression = NavigationExpansionHelpers.CreateNullKeyExpression(
                navigationKeyAccessExpression.Type,
                keyCount: 1);

            var newNavigationExpansionExpressionState = new NavigationExpansionExpressionState(
                navigationExpansionExpression.State.CurrentParameter,
                navigationExpansionExpression.State.SourceMappings,
                Expression.Lambda(navigationKeyAccessExpression, navigationExpansionExpression.State.PendingSelector.Parameters[0]),
                applyPendingSelector: true,
                navigationExpansionExpression.State.PendingOrderings,
                navigationExpansionExpression.State.PendingIncludeChain,
                // we need to remap cardinality reducing operator since it's source type has now changed
                navigationExpansionExpression.State.PendingCardinalityReducingOperator?.GetGenericMethodDefinition().MakeGenericMethod(navigationKeyAccessExpression.Type),
                navigationExpansionExpression.State.CustomRootMappings,
                navigationExpansionExpression.State.MaterializeCollectionNavigation);

            var navigationExpression = new NavigationExpansionExpression(
                navigationExpansionExpression.Operand,
                newNavigationExpansionExpressionState,
                navigationKeyAccessExpression.Type);

            return(navigationExpression, nullKeyExpression);
        }
Пример #2
0
        private NavigationBindingExpression CreateParentBindingExpression(NavigationBindingExpression navigationBindingExpression)
        {
            // TODO: verify this is correct in all cases
            var parentNavigationEntityType = navigationBindingExpression.NavigationTreeNode.Navigation.FindInverse().GetTargetType();
            var parentTreeNode             = navigationBindingExpression.NavigationTreeNode.Parent;

            parentTreeNode.Children.Remove(navigationBindingExpression.NavigationTreeNode);

            return(new NavigationBindingExpression(
                       navigationBindingExpression.RootParameter,
                       parentTreeNode,
                       parentNavigationEntityType,
                       navigationBindingExpression.SourceMapping,
                       parentNavigationEntityType.ClrType));
        }
        public static Expression CreateCollectionNavigationExpression(
            NavigationTreeNode navigationTreeNode, ParameterExpression rootParameter, SourceMapping sourceMapping)
        {
            var collectionEntityType = navigationTreeNode.Navigation.ForeignKey.DeclaringEntityType;

            Expression operand;

            if (navigationTreeNode.IncludeState == NavigationState.Pending ||
                navigationTreeNode.ExpansionState == NavigationState.Pending)
            {
                var entityQueryable = (Expression)NullAsyncQueryProvider.Instance.CreateEntityQueryableExpression(collectionEntityType.ClrType);

                var outerBinding = new NavigationBindingExpression(
                    rootParameter,
                    navigationTreeNode.Parent,
                    navigationTreeNode.Navigation.DeclaringEntityType,
                    sourceMapping,
                    navigationTreeNode.Navigation.DeclaringEntityType.ClrType);

                var outerKeyAccess = NavigationExpansionHelpers.CreateKeyAccessExpression(
                    outerBinding,
                    navigationTreeNode.Navigation.ForeignKey.PrincipalKey.Properties,
                    addNullCheck: outerBinding.NavigationTreeNode.Optional);

                var collectionCurrentParameter = Expression.Parameter(
                    collectionEntityType.ClrType, collectionEntityType.ClrType.GenerateParameterName());

                var innerKeyAccess = NavigationExpansionHelpers.CreateKeyAccessExpression(
                    collectionCurrentParameter,
                    navigationTreeNode.Navigation.ForeignKey.Properties);

                var predicate = Expression.Lambda(
                    CreateKeyComparisonExpressionForCollectionNavigationSubquery(
                        outerKeyAccess,
                        innerKeyAccess,
                        outerBinding),
                    collectionCurrentParameter);

                operand = Expression.Call(
                    LinqMethodHelpers.QueryableWhereMethodInfo.MakeGenericMethod(collectionEntityType.ClrType),
                    entityQueryable,
                    predicate);
            }
            else
            {
                operand = new NavigationBindingExpression(
                    rootParameter,
                    navigationTreeNode,
                    collectionEntityType,
                    sourceMapping,
                    collectionEntityType.ClrType);
            }

            var result = NavigationExpansionHelpers.CreateNavigationExpansionRoot(
                operand, collectionEntityType, navigationTreeNode.Navigation);

            // this is needed for cases like: root.Include(r => r.Collection).ThenInclude(c => c.Reference).Select(r => r.Collection)
            // result should be elements of the collection navigation with their 'Reference' included
            var newSourceMapping = result.State.SourceMappings.Single();

            IncludeHelpers.CopyIncludeInformation(navigationTreeNode, newSourceMapping.NavigationTree, newSourceMapping);

            return(result);
        }