A cycle was detected in a LINQ expression exception

前端 未结 4 1727
执笔经年
执笔经年 2020-12-09 20:36

I get the error :

A cycle was detected in a LINQ expression.

in ToList() while trying to do the following:

相关标签:
4条回答
  • 2020-12-09 21:13

    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();
    }
    
    0 讨论(0)
  • 2020-12-09 21:17

    Why are you assigning to your parameter? Why not

    private IEnumerable<int> FilterIdsByClient(IEnumerable<int> entityIds) 
    { 
        return
            MyObjectContext.CreateObjectSet<TEntity>() 
                .Where(x => x.ClientId == _clientId) 
                .Where(x => entityIds.Contains(x.Id)) 
                .Select(x => x.Id)
                .ToList(); 
    } 
    
    0 讨论(0)
  • 2020-12-09 21:30

    The answer is to not assign the LINQ query to entityIds. See @Stu's answer for a solution.

    0 讨论(0)
  • 2020-12-09 21:30

    Of course there is a cycle. You are using entityIds in the Where Linq Extension method and it is the query being constructed itself. Instead of modifying the inputted IEnumerable, return a new query as follows:

    private IEnumerable<int> FilterIdsByClient(IEnumerable<int> entityIds)
    {
        var query =
            MyObjectContext.CreateObjectSet<TEntity>()
                .Where(x => x.ClientId == _clientId)
                .Where(x => entityIds.Contains(x.Id))
                .Select(x => x.Id);
    
        return query.ToList();
    }
    
    0 讨论(0)
提交回复
热议问题