我有一个连接数据库中多个表的 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() 时只需要一次访问数据库。
为了提高重构后查询的性能,可以尝试使用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);
重构版本中的每个较小的连接都创建一个匿名类型,需要在最终连接中具体化为 UserAccountDetails 类的对象。物化涉及创建对象并根据从数据库返回的数据设置它们的属性。这个过程可能很耗时,尤其是在有大量行的情况下