使用 GroupBy 从查询中获取字典

Getting a Dictionary from a Query with GroupBy

给定两个持久化实体

public class Header
{
    public virtual int Id { get; set; }

    public virtual string Name { get; set; }

    public virtual List<Detail> Details { get; set; }
}

public class Detail
{
    public virtual int Id { get; set; }

    public virtual Header MyHeader { get; set; }

    public virtual string Text { get; set; }

    public virtual object LotsOfPropertiesIDontNeed { get; set; }
}

我想填充一个新的object

public class MiniHeader
{
    public string Name { get; set; }

    public Dictionary<int, string> DetailTexts { get; set; }
}

仅包含 Header 中的名称,以及将详细信息 ID 与相关文本相关联的字典。请注意 Detail 也有 LotsOfPropertiesIDontNeed,我不想拉 通过网络甚至来自 SQL 服务器的请求。

用代码

IEnumerable<MiniHeader> mini =
    ctx.Details.Include(d => d.MyHeader)
    .GroupBy(d => d.MyHeader)
    .Select(g => new MiniHeader()
    {
        Name = g.Key.Name,
        DetailTexts = g.ToDictionary(d => d.Id, d => d.Text)
    });

我得到了预期

LINQ to Entities does not recognize the method 'System.Collections.Generic.Dictionary`2[System.Int32,System.String]

因为 .ToDictionary 不能在数据库端执行。我可以让它像这样工作:

IEnumerable<MiniHeader> mini =
    ctx.Details.Include(d => d.MyHeader)
    .GroupBy(d => d.MyHeader)
    .AsEnumerable()
    .Select(g => new MiniHeader()
    {
        Name = g.Key.Name,
        DetailTexts = g.ToDictionary(d => d.Id, d => d.Text)
    });

但我推测 LotsOfPropertiesIDontNeed 将被 SQL 服务器请求并通过网络拉取。

有没有办法在不拉出不必要的字段的情况下完成这项工作?

您可以将结果投射到匿名类型,然后将 AsEnumerable 和以后的项目应用到您的 class,例如:

IEnumerable<MiniHeader> mini =
    ctx.Details.Include(d => d.MyHeader)
    .GroupBy(d => d.MyHeader)
    .Select(g => new
    {
        Name = g.Key.Name,
        Details = g.Select(i => new { i.Id, i.Text }),
    })
    .AsEnumerable()
    .Select(e => new MiniHeader()
    {
        Name = e.Name,
        DetailTexts = e.Details.ToDictionary(d => d.Id, d => d.Text)
    });

这将让您只获得您需要的那些字段,稍后您可以在内存中的集合上使用 ToDictionary