在LINQ EX pression异常检测到循环 [英] A cycle was detected in a LINQ expression exception

查看:579
本文介绍了在LINQ EX pression异常检测到循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到的错误:

一个周期的LINQ EX pression检测。

A cycle was detected in a LINQ expression.

了ToList()试着做到以下几点:

private IEnumerable<int> FilterIdsByClient(IEnumerable<int> entityIds)
{
    entityIds =
        MyObjectContext.CreateObjectSet<TEntity>()
            .Where(x => x.ClientId == _clientId)
            .Where(x => entityIds.Contains(x.Id))
            .Select(x => x.Id);

    return entityIds.ToList();
}

然而,这并不抛出任何异常,正常工作

This however doesn't throw any exception and works fine:

private IEnumerable<int> FilterIdsByClient(IEnumerable<int> entityIds)
{
    entityIds =
        MyObjectContext.CreateObjectSet<TEntity>()
            .Where(x => x.ClientId == _clientId)
            .Where(x => entityIds.Contains(x.Id))
            .Select(x => x.Id)
            .ToList();

    return entityIds;
}

(当然,这是一个简化的版本)。

(This is a simplfied version of course).

任何人都有一个线索,为什么这种奇怪的行为发生?

Anyone have a clue why this strange behavior happens?

编辑:

这是堆栈跟踪:

   at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.Visit(Expression exp)
   at System.Data.Objects.ELinq.Funcletizer.Funcletize(Expression expression, Func`1& recompileRequired)
   at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.InlineExpression(Expression exp)
   at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.InlineObjectQuery(ObjectQuery inlineQuery, Type expressionType)
   at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.InlineValue(Expression expression, Boolean recompileOnChange)
   at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.Visit(Expression exp)
   at System.Linq.Expressions.EntityExpressionVisitor.VisitExpressionList(ReadOnlyCollection`1 original)
   at System.Linq.Expressions.EntityExpressionVisitor.VisitMethodCall(MethodCallExpression m)
   at System.Linq.Expressions.EntityExpressionVisitor.Visit(Expression exp)
   at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.Visit(Expression exp)
   at System.Linq.Expressions.EntityExpressionVisitor.VisitLambda(LambdaExpression lambda)
   at System.Linq.Expressions.EntityExpressionVisitor.Visit(Expression exp)
   at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.Visit(Expression exp)
   at System.Linq.Expressions.EntityExpressionVisitor.VisitUnary(UnaryExpression u)
   at System.Linq.Expressions.EntityExpressionVisitor.Visit(Expression exp)
   at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.Visit(Expression exp)
   at System.Linq.Expressions.EntityExpressionVisitor.VisitExpressionList(ReadOnlyCollection`1 original)
   at System.Linq.Expressions.EntityExpressionVisitor.VisitMethodCall(MethodCallExpression m)
   at System.Linq.Expressions.EntityExpressionVisitor.Visit(Expression exp)
   at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.Visit(Expression exp)
   at System.Linq.Expressions.EntityExpressionVisitor.VisitExpressionList(ReadOnlyCollection`1 original)
   at System.Linq.Expressions.EntityExpressionVisitor.VisitMethodCall(MethodCallExpression m)
   at System.Linq.Expressions.EntityExpressionVisitor.Visit(Expression exp)
   at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.Visit(Expression exp)
   at System.Data.Objects.ELinq.Funcletizer.Funcletize(Expression expression, Func`1& recompileRequired)
   at System.Data.Objects.ELinq.ExpressionConverter..ctor(Funcletizer funcletizer, Expression expression)
   at System.Data.Objects.ELinq.ELinqQueryState.CreateExpressionConverter()
   at System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
   at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at ...FilterIdsByClient...

EDIT2:

应该注意,在这种情况下,的IEnumerable&LT; INT&GT; entityIds 是一个列表,一个Ajax请求,而不是从什么地方查询正在添加。

Should note that in this case, IEnumerable<int> entityIds is a list comming from an ajax request and not a query from somewhere.

推荐答案

行为似乎有些奇怪,因为你没有正确地考虑关闭语义。请参阅下面的注释:

The behavior seems strange because you are not considering the closure semantics correctly. See the comments below:

private IEnumerable<int> FilterIdsByClient(IEnumerable<int> entityIds) 
{ 
    // The variable entityIds points to whatever was passed in: A List, according to the edited question.

    entityIds =                                    //this is an assignment, changing the referent of entityIds
        MyObjectContext.CreateObjectSet<TEntity>() 
            .Where(x => x.ClientId == _clientId) 
            .Where(x => entityIds.Contains(x.Id))  //this lambda closes over the variable entityIds
            .Select(x => x.Id); 

    // The query now has a reference to the *variable* entityIds, not to the object that entityIds pointed to originally.
    // The value of entityIds has been changed; it now points to the query itself!
    // The query is therefore operating on itself; this causes the "cycle detected" message.
    // Because of delayed execution, the query is not executed until the next line of code:

    return entityIds.ToList();
}

这篇关于在LINQ EX pression异常检测到循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆