Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对嵌套数据使用Linq(工具包)的StackOverflowException_C#_Linq_Nested_Stack Overflow_Linqkit - Fatal编程技术网

C# 对嵌套数据使用Linq(工具包)的StackOverflowException

C# 对嵌套数据使用Linq(工具包)的StackOverflowException,c#,linq,nested,stack-overflow,linqkit,C#,Linq,Nested,Stack Overflow,Linqkit,我正在尝试使用Linq/LinqKit构建嵌套查询。理论上这似乎很容易。但我还是坚持实用的部分 在我的数据库中,我有一个表,该表具有对其父表的自引用。在我的linq查询中,我现在想要选择给定元素的所有父元素(以及这个元素的父元素,以此类推) 在我的代码中,MyTable的分部类中有以下表达式: public static Expression<Func<MyTable, IEnumerable<MyTable>>> Parents => (entity)

我正在尝试使用Linq/LinqKit构建嵌套查询。理论上这似乎很容易。但我还是坚持实用的部分

在我的数据库中,我有一个表,该表具有对其父表的自引用。在我的linq查询中,我现在想要选择给定元素的所有父元素(以及这个元素的父元素,以此类推)

在我的代码中,
MyTable
的分部类中有以下表达式:

public static Expression<Func<MyTable, IEnumerable<MyTable>>> Parents => (entity) => entity.ParentId != null ? new[]{entity.ParentEntity}.Union(Parents.Invoke(entity.ParentEntity) : new MyEntity[]{};
运行此代码会导致堆栈溢出异常,因为没有达到停止条件,因此
Parents
-调用会无限嵌套,直到堆栈满为止

有没有办法做到这一点,或者这是不可能的?或者在一个查询中使用
Linq
/
LinqKit
还有其他方法获取嵌套数据吗

我已经尝试将上下文传递给表达式以创建子查询(也不起作用):

publicstaticexpressionparents=>(entity,dbContext)=>entity.ParentId!=无效的new[]{entity.ParentEntity}.Union(Parents.Invoke(dbContext.MyTable.FirstOrDefault(x=>x.Id==entity.ParentId),dbContext):new MyEntity[]{};

如注释中所述,目前无法创建递归可扩展(即不可调用)表达式

但是,如果可以限制最大深度,一种可能的解决方案是构建如下表达式(利用EF导航属性):

动态地:

static Expression<Func<MyTable, IEnumerable<MyTable>>> ParentsSelector(int maxLevels)
{
    var parameter = Expression.Parameter(typeof(MyTable), "x");
    var parents = new Expression[maxLevels];
    for (int i = 0; i < parents.Length; i++)
        parents[i] = Expression.Property(i > 0 ? parents[i - 1] : parameter, "Parent");
    Expression<Func<MyTable, bool>> predicate = x => x != null;
    var result = Expression.Call(
        typeof(Enumerable), "Where", new[] { parameter.Type },
        Expression.NewArrayInit(parameter.Type, parents), predicate);
    return Expression.Lambda<Func<MyTable, IEnumerable<MyTable>>>(result, parameter);
}

嗨,有趣的尝试!但不,不可能创建可扩展(EF兼容)具有未知最大嵌套级别的递归表达式,因为没有SQL CTE的等效项。@IvanStoev,如果我知道嵌套的最大级别,该怎么办?已尝试传递一个深度参数,该参数会随着每次递归调用而递减。但这里有相同的异常
public static Expression<Func<MyTable, MyContext, IEnumerable<MyTable>>> Parents => (entity, dbContext) => entity.ParentId != null ? new[]{entity.ParentEntity}.Union(Parents.Invoke(dbContext.MyTable.FirstOrDefault(x => x.Id == entity.ParentId), dbContext) : new MyEntity[]{};
Parents = new MyTable [] { x.Parent, x.Parent.Parent, x.Parent.Parent.Parent, ...}
    .Where(e => e != null)
static Expression<Func<MyTable, IEnumerable<MyTable>>> ParentsSelector(int maxLevels)
{
    var parameter = Expression.Parameter(typeof(MyTable), "x");
    var parents = new Expression[maxLevels];
    for (int i = 0; i < parents.Length; i++)
        parents[i] = Expression.Property(i > 0 ? parents[i - 1] : parameter, "Parent");
    Expression<Func<MyTable, bool>> predicate = x => x != null;
    var result = Expression.Call(
        typeof(Enumerable), "Where", new[] { parameter.Type },
        Expression.NewArrayInit(parameter.Type, parents), predicate);
    return Expression.Lambda<Func<MyTable, IEnumerable<MyTable>>>(result, parameter);
}
var parents = ParentsSelector(10);
var query = dbContext.MyTable
    .AsExpandable()
    .Where(x => x.Id == myId)
    .Select(x => new
    {
        Parents = parents.Invoke(x)
    });