【问题标题】:How to include high number of sub entities?如何包含大量子实体?
【发布时间】:2015-11-20 16:21:54
【问题描述】:

我正在使用 EF7,只是想知道是否有更快的方法来将所有子实体包含在实体中。

我的课程:

public class A
{
    public int Id { get; set; }
    public int Name { get; set; }
    public virtual B B { get; set; }
    public virtual C B { get; set; }
}

 public class B
{
    public int Id { get; set; }
    public int Name { get; set; }
    public virtual BA BA { get; set; }
    public virtual BB BB { get; set; }
}

public class C
{
    public int Id { get; set; }
    public int Name { get; set; }
    public virtual CA CA { get; set; }
    public virtual CB CB { get; set; }
    public virtual CC CC { get; set; }
}

这就是我目前的做法,包括所有子实体。

A test = _dbContext.As.Where(a => a.Id == id)
         .Include(a => a.B)
             .ThenInclude(b => b.BA)
         .Include(a => a.B)
             .ThenInclude(b => b.BB)
         .Include(a => a.C) 
             .ThenInclude(c => c.CA)
         .Include(a => a.C) 
             .ThenInclude(c => c.CB)
         .Include(a => a.C) 
             .ThenInclude(c => c.CC)

这对小的层次结构很好,但如果实体很大,就会有很多重复。

我不想关闭延迟加载。

这就是我将查询传递给前端的方式:

[Route("api/Test/{id}")]
    [HttpGet]
    public A Get(int id)
    {
        A test = _dbContext.As.Where(a => a.Id == id)
         .Include(a => a.B)
             .ThenInclude(b => b.BA)
         .Include(a => a.B)
             .ThenInclude(b => b.BB)
         .Include(a => a.C) 
             .ThenInclude(c => c.CA)
         .Include(a => a.C) 
             .ThenInclude(c => c.CB)
         .Include(a => a.C) 
             .ThenInclude(c => c.CC)

        return test;
    }

这是我在Startup.csConfigureServices下的内容:

services.AddMvc().AddJsonOptions(options =>
        {
            options.SerializerSettings.ContractResolver =
                new CamelCasePropertyNamesContractResolver();
            options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        });

【问题讨论】:

  • 等等,如果您使用延迟加载,则不必包含所有实体;访问时会自动包含它们。
  • 如果我想将它们发送到网络前端,则不是。
  • 这不是真的,问题是你没有迭代属性......你必须迭代属性(通常在另一个类或匿名对象中转换你需要的所有内容)。提供将查询发送到前端的代码,我会告诉你如何做到这一点
  • 感谢法比奥,问题已编辑
  • @Fabio Luz,依赖延迟加载会影响性能,因为对尚未加载的属性的每次访问都会导致对数据库的额外查询。响应序列化时会枚举action方法返回的可查询对象,返回实体的所有属性都会被序列化器访问,导致对DB的大量查询,显着减慢响应(称为SELECT N+1问题) )。在这种情况下,应优先使用包含而不是延迟加载,因为只有一个带有 JOIN 的“大”查询会在数据库上执行。

标签: entity-framework entity-framework-core


【解决方案1】:

创建一个类AViewModel来表示你发送到视图的数据,然后修改你的方法如下:

[Route("api/Test/{id}")]
[HttpGet]
public A Get(int id)
{
    List<AViewModel> test = _dbContext.As.Where(a => a.Id == id)
    .Select(i => new AViewModel
      {
         a = B.BA,
         b = B.BB,
         c = C.CA,
         d = C.CB,
         e = C.CE
      }).ToList();

    return test;
}

这样做您不必包含所有属性,它们将在序列化时自动包含在内。但是,正如@felix-b 所说,这会影响性能,因为它会生成几个对 DB 的查询。最好使用包含而不是延迟加载。

【讨论】:

    猜你喜欢
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多