消除LINQ to Entities中的循环

时间:2015-03-27 18:10:42

标签: c# linq entity-framework entity-framework-6

如何重新编写以下查询以消除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;

2 个答案:

答案 0 :(得分:2)

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

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();

答案 1 :(得分:1)

使用来自allTablesRecords的通配符对键进行投影,然后使用查询中的contains进行比较。仅当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();