EntityFramework Core使用匿名类加载相关数据会导致多个子选择

时间:2016-12-15 15:29:22

标签: asp.net-core entity-framework-core

我认识到,当我使用.NET Core Web API中的Entity Framework Core查询具有相关数据的对象列表时,只要我不尝试使用匿名类隐藏某些字段,它就能正常工作。

当我使用匿名类时,相关数据从DB加载,每个条目都有一个调用。在下面的示例中,这意味着为每个人创建数据库调用以查询相关详细信息(根据日志文件)。

由于人员名单很长,这意味着数据库受到我试图避免的查询的影响。

两个表的简单情况:

Person (id, firstname, lastname, someOtherField)

PersonDetails (id, PersonId, DetailText, someOtherDetailField)

如果我选择所有字段并使用预先加载,它可以完美地使用一个数据库调用。

鉴于此代码:


public IActionResult Get()
{
    var result = _db.Media.Include(m => m.Thumbnail);
    return Ok(result);
}

产生如下输出:


[
  {
    "id": 1,
    "firstname": "First1",
    "lastname": "Last1",
    "groupAssignment": [],
    "personDetails": [
      {
        "id": 1,
        "personId": 1,
        "detailText": "details1"
      }
    ]
  }
]

我正在寻找的输出只在Person上选择了字段,而且只在PersonDetails上选择了字段,如下:


[
  {
    "firstname": "First1",
    "lastname": "Last1",
    "personDetails": [
      {
        "detailText": "details1"
      }
    ]
  }
]

目前,我正处于这个状态,使用一个匿名的类隐藏人物字段:


public IActionResult Get()
{
    var result = _dbContext.Person
                    .Include(p => p.PersonDetails)
                    .Select(
                        p => new
                        {
                            p.Firstname,
                            p.Lastname,
                            p.PersonDetails
                        }
                    );
    return Ok(result);
}

但这给我留下了两个问题:

  1. 我为每个Person创建一个单独的数据库查询来请求PersonDetails
  2. 由于某种原因,我无法使用
    p.PersonDetails.Select(d => new {d.DetailText})
    来过滤PersonDetails的字段。
  3. 有关如何查询/返回所需输出的任何建议吗?

1 个答案:

答案 0 :(得分:0)

从其他问题的答案中我发现存在两个问题

.AsEnumerable()使EF通过一次调用查询相关数据(这并不意味着整个查询是一次调用,但至少通过一次调用查询所有相关数据)

personDetails =使匿名数据成为命名var,只允许选择特定字段。


public IActionResult Get()
{
    var result = _dbContext.Person
        .Include(p => p.PersonDetails)
        .AsEnumerable()
        .Select(
            p => new
            {
                p.Firstname,
                p.Lastname,
                personDetails = p.PersonDetails.Select(d => new {d.DetailsText} )
            }
        );
    return Ok(result);
}