c# - StackOverflowException 对嵌套数据使用 Linq(Kit)

标签 c# linq nested stack-overflow linqkit

我正在尝试使用 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[]{};

ParentId 时,应该选择给定实体的父级和那些父级已设置。

查询本身(简化):

dbContext
    .MyTable
    .AsExpandable()
    .Where(x => x.Id == myId)
    .Select(x => new
    {
        Parents = MyTable.Parents.Invoke(x, dbContext)
    });

运行此代码以 StackOverflowException 结束。由于未达到停止条件,因此 Parents -调用无限嵌套,直到堆栈已满。

知道如何做到这一点,或者这不可能吗?或者是否有其他方法使用 Linq 获取嵌套数据/LinqKit在一个查询中?

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

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[]{};

最佳答案

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

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

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)
    });

关于c# - StackOverflowException 对嵌套数据使用 Linq(Kit),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41157984/

相关文章:

c# - 如何为 Azure Blob 存储中的文件夹生成共享访问签名?

c# - 在字典或相关集合中查找 'Next Available' 键

c# - 如何从 linq 表达式中获取字符串?

javascript - 打印嵌套的复杂对象

Matlab: "Error using assignin: Attempt to add "c"to a static workspace"

c# - 什么是交换 2 个整数变量的 C 代码

c# - 有没有一种简单的方法可以在 WPF 中创建一个 "tab-sensitive"按钮?

c# - 快速找到该对象的方法已更新

c# - 如何使用 Moles 通过 LINQ 重定向表中的选择?

c++ - 获取类似 STL 的嵌套容器中的元素总数