private bool IsGroupByAggregateSubQuery(QueryModel queryModel) { if (queryModel.MainFromClause.FromExpression.Type.IsGrouping() && queryModel.BodyClauses.Count == 0 && queryModel.ResultOperators.Count == 1 && _aggregateResultOperators.Contains(queryModel.ResultOperators[0].GetType()) && _queryModelStack.Count > 0 && !_queryModelStack.Peek().BodyClauses.OfType <IQuerySource>().Any()) { var groupResultOperator = (GroupResultOperator) ((SubQueryExpression) ((FromClauseBase)queryModel.MainFromClause.FromExpression.TryGetReferencedQuerySource()) .FromExpression) .QueryModel.ResultOperators.Last(); MemberAccessBindingExpressionVisitor.GetPropertyPath( queryModel.SelectClause.Selector, _queryModelVisitor.QueryCompilationContext, out var qsre); if (qsre != null || queryModel.SelectClause.Selector.RemoveConvert() is ConstantExpression || groupResultOperator.ElementSelector.NodeType == ExpressionType.New || groupResultOperator.ElementSelector.NodeType == ExpressionType.MemberInit) { return(true); } } return(false); }
private Expression RewriteNullEquality(ExpressionType nodeType, Expression nonNullExpression) { var properties = MemberAccessBindingExpressionVisitor .GetPropertyPath(nonNullExpression, _queryCompilationContext, out var qsre); if (properties.Count > 0 && properties[properties.Count - 1] is INavigation lastNavigation && lastNavigation.IsCollection()) { // collection navigation is only null if its parent entity is null (null propagation thru navigation) // it is probable that user wanted to see if the collection is (not) empty // log warning suggesting to use Any() instead. _queryCompilationContext.Logger .PossibleUnintendedCollectionNavigationNullComparisonWarning(properties); return(Visit( Expression.MakeBinary( nodeType, UnwrapLastNavigation(nonNullExpression), Expression.Constant(null)))); } if (IsInvalidSubQueryExpression(nonNullExpression)) { return(null); } var entityType = _model.FindEntityType(nonNullExpression.Type) ?? GetEntityType(properties, qsre); if (entityType == null) { return(null); } var keyProperties = entityType.FindPrimaryKey().Properties; var nullCount = keyProperties.Count; Expression keyAccessExpression; // Skipping composite key with subquery since it requires to copy subquery // which would cause same subquery to be visited twice if (nullCount > 1 && nonNullExpression.RemoveConvert() is SubQueryExpression) { return(null); } if (properties.Count > 0 && properties[properties.Count - 1] is INavigation navigation2 && navigation2.IsDependentToPrincipal()) { keyAccessExpression = CreateKeyAccessExpression( UnwrapLastNavigation(nonNullExpression), navigation2.ForeignKey.Properties, nullComparison: false); nullCount = navigation2.ForeignKey.Properties.Count; }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { var newMethodCallExpression = (MethodCallExpression)base.VisitMethodCall(methodCallExpression); Expression newLeftExpression = null; Expression newRightExpression = null; if (newMethodCallExpression.Method.Name == nameof(object.Equals) && newMethodCallExpression.Object != null && newMethodCallExpression.Arguments.Count == 1) { newLeftExpression = newMethodCallExpression.Object; newRightExpression = newMethodCallExpression.Arguments[0]; } if (newMethodCallExpression.Method.Equals(_objectEqualsMethodInfo)) { newLeftExpression = newMethodCallExpression.Arguments[0]; newRightExpression = newMethodCallExpression.Arguments[1]; } if (newLeftExpression != null && newRightExpression != null) { var isLeftNullConstant = newLeftExpression.IsNullConstantExpression(); var isRightNullConstant = newRightExpression.IsNullConstantExpression(); if (isLeftNullConstant && isRightNullConstant) { return(newMethodCallExpression); } if (isLeftNullConstant || isRightNullConstant) { var result = RewriteNullEquality( ExpressionType.Equal, isLeftNullConstant ? newRightExpression : newLeftExpression); if (result != null) { return(result); } } var leftEntityType = _model.FindEntityType(newLeftExpression.Type) ?? MemberAccessBindingExpressionVisitor.GetEntityType(newLeftExpression, _queryCompilationContext); var rightEntityType = _model.FindEntityType(newRightExpression.Type) ?? MemberAccessBindingExpressionVisitor.GetEntityType(newRightExpression, _queryCompilationContext); if (leftEntityType != null && rightEntityType != null) { if (leftEntityType.RootType() == rightEntityType.RootType()) { var result = RewriteEntityEquality(ExpressionType.Equal, newLeftExpression, newRightExpression); if (result != null) { return(result); } } else { return(Expression.Constant(false)); } } } return(newMethodCallExpression); }