Entity Framework Core 中嵌套和扁平化 LINQ 连接查询的性能差异

问题描述 投票:0回答:2

我有一个连接数据库中多个表的 LINQ 查询。原查询如下:

var result = await (from u in _context.TableA
                    join au in _context.TableB on u.UserRowId equals au.UserRowId into auf
                    from au in auf.DefaultIfEmpty()
                    join a in _context.TableC on au.AccountRowId equals a.AccountRowId into af
                    from a in af.DefaultIfEmpty()
                    join aur in _context.TableD on new { A = a.AccountRowId, B = u.UserRowId } equals new { A = aur.AccountRowId, B = aur.UserRowId } into aurf
                    from aur in aurf.DefaultIfEmpty()
                    join r in _context.TableE on aur.RoleRowId equals r.RoleRowId into rf
                    from r in rf.DefaultIfEmpty()
                    select new UserAccountDetails { userDbModels = u, accountDbModels = a, roleDbModels = r, accountUserDbModels = au })
                    .ToListAsync().ConfigureAwait(false);

为了提高可读性,我将查询重构为几个更小的连接。查询的重构版本如下:

var tableA_B_Join = from u in _context.TableA
                    join au in _context.TableB on u.UserRowId equals au.UserRowId into auf
                    from au in auf.DefaultIfEmpty()
                    select new { TableA = u, TableB = au };

var tableA_B_C_Join = from tab in tableA_B_Join
                      join a in _context.TableC on tab.TableB.AccountRowId equals a.AccountRowId into af
                      from a in af.DefaultIfEmpty()
                      select new { TableA = tab.TableA, TableB = tab.TableB, TableC = a };

var tableA_B_C_D_Join = from tab in tableA_B_C_Join
                        join aur in _context.TableD on new { A = tab.TableC.AccountRowId, B = tab.TableA.UserRowId } equals new { A = aur.AccountRowId, B = aur.UserRowId } into aurf
                        from aur in aurf.DefaultIfEmpty()
                        select new { TableA = tab.TableA, TableB = tab.TableB, TableC = tab.TableC, TableD = aur };

var tableA_B_C_D_E_Join = from tab in tableA_B_C_D_Join
                          join r in _context.TableE on tab.TableD.RoleRowId equals r.RoleRowId into rf
                          from r in rf.DefaultIfEmpty()
                          select new UserAccountDetails
                          {
                              userDbModels = tab.TableA,
                              accountDbModels = tab.TableC,
                              roleDbModels = r,
                              accountUserDbModels = tab.TableB
                          };

// Execute the final query and return the result
var result = await tableA_B_C_D_E_Join.ToListAsync().ConfigureAwait(false);

但是,我注意到重构版本的执行时间比原始查询更长。原始查询耗时 0.91 秒,而重构版本耗时 1.25 秒。我想知道是什么导致了延迟,特别是因为重构版本在我调用 ToListAsync() 时只需要一次访问数据库。

c# entity-framework linq
2个回答
0
投票

为了提高重构后查询的性能,可以尝试使用Include方法来热加载相关实体。这可以减少 Entity Framework Core 需要执行的 SQL 查询的数量,并且可以提高查询的整体性能。比如你可以试试下面的代码:

var result = await _context.TableA
.Include(u => u.TableB)
.ThenInclude(au => au.TableC)
.Include(u => u.TableB)
.ThenInclude(au => au.TableD)
.ThenInclude(aur => aur.Role)
.Select(u => new UserAccountDetails
{
userDbModels = u,
accountDbModels = u.TableB.TableC,
roleDbModels = u.TableB.TableD.Role,
accountUserDbModels = u.TableB
})
.ToListAsync().ConfigureAwait(false);

-1
投票

重构版本中的每个较小的连接都创建一个匿名类型,需要在最终连接中具体化为 UserAccountDetails 类的对象。物化涉及创建对象并根据从数据库返回的数据设置它们的属性。这个过程可能很耗时,尤其是在有大量行的情况下

© www.soinside.com 2019 - 2024. All rights reserved.