Linq to SQL генерирует исключение StackOverflowException

Я выполняю довольно простой запрос, используя Linq to SQL. Я создаю выражение, а затем передаю его в метод расширения Where (). Внутренние компоненты Linq выдают исключение StackOverflowException, когда я пытаюсь фактически выполнить запрос. Вот код:

int expectedCount = 4;
Expression> expression = ...;

//Expression looks like (LocaleID = 1 && GenderID ==1 && (TimeFrameID == 2007 || TimeFrameID == 2008))

using (XYZDataContext context = new XYZDataContext())
{
    int count = context.Things.Where(expression).Count();
    //...
}

А вот DebugView выражения:

.Lambda #Lambda1(XYZ.DataAccess.Thing $o)
{
    .Invoke (.Lambda #Lambda2)($o) & .Invoke (.Lambda #Lambda3)($o)
}

.Lambda #Lambda2(XYZ.DataAccess.Thing $o)
{
    .Invoke (.Lambda #Lambda4)($o) & .Invoke (.Lambda #Lambda5)($o)
}

.Lambda #Lambda3(XYZ.DataAccess.Thing $o)
{
    .Invoke (.Lambda #Lambda6)($o) | .Invoke (.Lambda #Lambda7)($o)
}

.Lambda #Lambda4(XYZ.DataAccess.Thing $o)
{
    $o.LocaleID == .Constant(1)
}

.Lambda #Lambda5(XYZ.DataAccess.Thing $o)
{
    $o.GenderID == .Constant(1)
}

.Lambda #Lambda6(XYZ.DataAccess.Thing $o)
{
    $o.TimeframeID == .Constant(2007)
}

.Lambda #Lambda7(XYZ.DataAccess.Thing $o)
{
    $o.TimeframeID == .Constant(2008)
}

Выражение кажется мне правильным и довольно тривиальным. Когда я читаю представление отладки, я вижу:

((LocaleID == 1 && GenderID == 1) && (TimeFrameID == 2007 || TimeFrameID == 2008))

. .. что правильно.

Обновление 1

Удалив один из внутренних предложений or'd, все работает нормально. Таким образом, наличие обоих внутренних предложений or'd каким-то образом нарушает перевод из LINQ в SQL.

Обновление 2

У меня проблемы с переходом отладчика в код .NET Framework - я пробовал использовать Reflector для делать это так же хорошо, как и просто Visual Studio. Я зашел один раз, но в целом вмешаться не получается. Единственный раз, когда я попал в исключение StackOverflowException, произошло в:

ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, object state, bool ignoreSyncCtx)

Обновление 3

Вот код, который используется для создания выражения. Слишком много кода для публикации, но его суть ниже. У меня есть классы, которые позволяют мне создавать сложный многоуровневый запрос и сериализовать его в JSON и XML. По сути, каждая часть запроса строится с использованием следующих методов, а затем используется Or ' d и And'd вместе:

public class LinqSearchField : ISearchField
{
    public string Name { get; private set; }
    public Expression> Selector { get; private set; }

    public Expression> LessThan(V value)
    {
        return Expression.Lambda>(Expression.LessThan(this.Selector.Body, GetConstant(value)), this.Selector.Parameters);
    }

    public Expression> LessThanOrEqual(V value)
    {
        return Expression.Lambda>(Expression.LessThanOrEqual(this.Selector.Body, GetConstant(value)), this.Selector.Parameters);
    }

    public Expression> Equal(V value)
    {
        return Expression.Lambda>(Expression.Equal(this.Selector.Body, GetConstant(value)), this.Selector.Parameters);
    }

    public Expression> NotEqual(V value)
    {
        return Expression.Lambda>(Expression.NotEqual(this.Selector.Body, GetConstant(value)), this.Selector.Parameters);
    }

    public Expression> GreaterThan(V value)
    {
        return Expression.Lambda>(Expression.GreaterThan(this.Selector.Body, GetConstant(value)), this.Selector.Parameters);
    }

    public Expression> GreaterThanOrEqual(V value)
    {
        return Expression.Lambda>(Expression.GreaterThanOrEqual(this.Selector.Body, GetConstant(value)), this.Selector.Parameters);
    }

    private ConstantExpression GetConstant(V value)
    {
        return Expression.Constant(value, typeof(V));
    }

    public Expression> Null()
    {
        return Expression.Lambda>(Expression.Equal(this.Selector.Body, Expression.Constant(null)), this.Selector.Parameters);
    }

    public Expression> NotNull()
    {
        return Expression.Lambda>(Expression.NotEqual(this.Selector.Body, Expression.Constant(null)), this.Selector.Parameters);
    }
}

Вот код And (код OR тот же, но с выражением. И вместо этого):

public static Expression> And(this Expression> expression1, Expression> expression2)
{
    ParameterExpression[] parameters = expression1.Parameters.Union(expression2.Parameters).Distinct(new ParameterExpressionComparer()).ToArray();
    InvocationExpression invocationExpression1 = Expression.Invoke(expression1, parameters);
    InvocationExpression invocationExpression2 = Expression.Invoke(expression2, parameters);
    Expression binaryExpression = null;

    //And the current expression to the previous one.
    binaryExpression = Expression.AndAlso(invocationExpression1, invocationExpression2); //Or OrElse.

    //Wrap the expression in a lambda.
    return Expression.Lambda>(binaryExpression, parameters);
}

Обновление 4

Вероятно, это будет неодобрительно, но вот , который воспроизводит эту проблему . Мне действительно нужно разобраться, что здесь происходит.

7
задан Josh M. 26 April 2011 в 14:13
поделиться