protected override Expression VisitMember(MemberExpression expression) { var isIdentifier = _isEntityDecider.IsIdentifier(expression.Expression.Type, expression.Member.Name); if (isIdentifier) { _hasIdentifier = true; } if (!isIdentifier) { _memberExpressionDepth++; } var result = base.VisitMember(expression); if (!isIdentifier) { _memberExpressionDepth--; } if (_isEntityDecider.IsEntity(expression.Type) && ((_requiresJoinForNonIdentifier && !_hasIdentifier) || _memberExpressionDepth > 0) && _joiner.CanAddJoin(expression)) { var key = ExpressionKeyVisitor.Visit(expression, null); return(_joiner.AddJoin(result, key)); } _hasIdentifier = false; return(result); }
public static string Visit(Expression expression, IDictionary <ConstantExpression, NamedParameter> parameters) { var visitor = new ExpressionKeyVisitor(parameters); visitor.Visit(expression); return(visitor.ToString()); }
// We would usually get NULL if one of our inner member expresions was null. // However, it's possible a method call will convert the null value from the failed join into a non-null value. // This could be optimized by actually checking what the method does. For example StartsWith("s") would leave null as null and would still allow us to inner join. //protected override Expression VisitMethodCall(MethodCallExpression expression) //{ // Expression result = base.VisitMethodCall(expression); // return result; //} protected override Expression VisitMember(MemberExpression expression) { // The member expression we're visiting might be on the end of a variety of things, such as: // a.B // a.B.C // (a.B ?? a.C).D // I'm not sure what processing re-linq does to strange member expressions. // TODO: I suspect this code doesn't add the right joins for the last case. var isIdentifier = _isEntityDecider.IsIdentifier(expression.Expression.Type, expression.Member.Name); if (!isIdentifier) { _memberExpressionDepth++; } var result = base.VisitMember(expression); if (!isIdentifier) { _memberExpressionDepth--; } ExpressionValues values = _values.Pop().Operation(pvs => pvs.MemberAccess(expression.Type)); if (_isEntityDecider.IsEntity(expression.Type)) { // Don't add joins for things like a.B == a.C where B and C are entities. // We only need to join B when there's something like a.B.D. var key = ExpressionKeyVisitor.Visit(expression, null); if (_memberExpressionDepth > 0 && _joiner.CanAddJoin(expression)) { result = _joiner.AddJoin(result, key); } values.MemberExpressionValuesIfEmptyOuterJoined[key] = PossibleValueSet.CreateNull(expression.Type); } SetResultValues(values); return(result); }