c# - 在不使用 Include 的情况下选择具有多个嵌套级别的实体

标签 c# entity-framework linq

我有以下实体:

public class Item 
{
    public int Id { get; set; }

    public int? ParentId { get; set; }
    public Item Parent { get; set; }
    public List<Item> Children { get; set; }

    public double PropertyA { get; set; }
    public double PropertyB { get; set; }
    ...
}

现在我想查询数据库并检索所有嵌套子项的数据。 我可以通过使用 Eager Loading 和 Include() 来实现这一点:

var allItems = dbContext.Items
                    .Include(x => Children)
                    .ToList();

但是我想做以下投影而不是预加载:

public class Projection 
{
    public int Id { get; set; }
    public List<Projection> Children { get; set; }
    public double PropertyA { get; set; }
}

是否可以通过一次选择只检索所需的数据? 我们正在使用 Entity Framework 6.1.3。

编辑: 到目前为止,这是我尝试过的。 我真的不知道如何告诉 EF 以与他们的 parent 相同的方式映射所有 child Projection

An unhandled exception of type 'System.NotSupportedException' occurred in EntityFramework.SqlServer.dll

Additional information: The type 'Projection' appears in two structurally incompatible initializations within a single LINQ to Entities query. A type can be initialized in two places in the same query, but only if the same properties are set in both places and those properties are set in the same order.

var allItems = dbContext.Items
    .Select(x => new Projection
    {
        Id = x.Id,
        PropertyA = x.PropertyA,
        Children = x.Children.Select(c => new Projection()
        {
            Id = c.Id,
            PropertyA = c.PropertyA,
            Children = ???
        })
    })
    .ToList();

最佳答案

一般来说,您不能在单个 SQL 查询中加载未知无限深度的递归结构,除非您批量加载所有可能相关的数据,无论它们是否属于所请求的结构。

因此,如果您只想限制加载的列(不包括 PropertyB)但可以加载所有行,则结果可能如下所示:

var parentGroups = dbContext.Items.ToLookup(x => x.ParentId, x => new Projection
{
    Id = x.Id,
    PropertyA = x.PropertyA
});

// fix up children
foreach (var item in parentGroups.SelectMany(x => x))
{
    item.Children = parentGroups[item.Id].ToList();
}

如果你想限制加载的行数,你必须接受多个数据库查询才能加载子条目。例如,加载单个子集合可能如下所示

entry.Children = dbContext.Items
    .Where(x => x.ParentId == entry.Id)
    .Select(... /* projection*/)
    .ToList()

关于c# - 在不使用 Include 的情况下选择具有多个嵌套级别的实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40660116/

相关文章:

C# 与 C++ 安全性

c# - Xamarin AppCenter Crashes.TrackError 没有显示我在 AppCenter 中期望的详细信息

c# - 有没有像 DbSet<T>.RemoveWhere(Predicate<T>) 这样的东西

c# - 具有自动完成功能的文本框

c# - 基于多个字段对对象进行排名

c# - 是否应该路由 MVVM 事件?

C#Excel : Programmatically open and copy workbook while ignoring dependency

.net - Azure 函数 .net 5 UseSqlServer 配置

sql-server - 使用 LINQ 按左连接表中的特定列求和时排除空值

c# - 使用 Expression.Call 调用 SelectMany - 参数错误