消除 LINQ to Entities 中的循环

Eliminating Loop in LINQ to Entities

我如何修改下面的查询以消除 foreach 循环并对数据库进行一次调用?

List<AuditLog> auditLogs = new List<AuditLog>();

foreach (TableRecordGuidPair pair in allTablesRecords)
{
    var auditLogsFromDatabase = databaseContext.AuditLog.OrderBy(x => x.EventDateUtc)
      .Where
        (x => x.TableName == pair.TableName && 
         x.RecordId == pair.RecordID)
        .Select(auditLog => new AuditLog
        {
            AuditLogId = auditLog.AuditLogId,
        }).ToList();
    auditLogs.AddRange(auditLogsFromDatabase);
}

return auditLogs;

您可以使用 SelectMany select 所有列表,如下所示:

return allTablesRecords
    .SelectMany(pair => 
        databaseContext.AuditLog.OrderBy(x => x.EventDateUtc)
            .Where(x => x.TableName == pair.TableName && x.RecordId == pair.RecordID)
            .Select(auditLog => new AuditLog
            {
                AuditLogId = auditLog.AuditLogId,
            })
    )
    .ToList();

或者,您可以进行连接

return (from allTableRecords pair
    join databaseContext.AuditLog auditLog
        on new { pair.TableName, pair.RecordId } equals new { auditLog.TableName, auditLog.RecordId }
    select new {
        AutitLogId = auditLog.AuditLogId
    })
    .ToList();

使用 allTablesRecords 中的通配符对键进行投影,然后在查询中使用包含进行比较。这仅在 allTablesRecords 的记录少于大约 5000 条时有效。如果不止于此,你可能会遇到运行时异常,应该考虑做一个存储过程。

IEnumerable<string> pairKeys = allTablesRecords.Select(pair => pair.TableName + "¿" + pair.RecordID);
return databaseContext.AuditLog.OrderBy(x => x.EventDateUtc)
    .Where(x => pairKeys.Contains(x.TableName + "¿" + x.RecordID))
    .Select(auditLog => new AuditLog
    {
        AuditLogId = auditLog.AuditLogId,
    }).ToList();