我知道这个问题得到了回答,我同意使用AsEnumerable()
是要走的路。但是,我想强调一个常见的场景,我通常会遇到AsEnumerable()
使用效率低下来解决此错误的地方。
来自关系数据的 .NET 语言集成查询
AsEnumerable() 运算符与 ToList() 和 ToArray() 不同,不会导致执行查询。它仍然被推迟。AsEnumerable() 运算符仅更改查询的静态类型,将 IQueryable 转换为 IEnumerable,欺骗编译器将查询的其余部分视为本地执行。
参考
- 我是否误解了 LINQ to SQL .AsEnumerable()?
- 了解 LINQ to SQL 中的 .AsEnumerable()
低效的方式
IEnumerable<InvoiceDTO> inefficientEnumerable =
(from a in db.Invoices
where a.Practice_Key == practiceKey.FirstOrDefault()
select a
).AsEnumerable().
Select(x => new InvoiceDTO
{
InvoiceID = x.InvoiceID,
PracticeShortName = x.Dim_Practice.Short_Name,
InvoiceDate = x.InvoiceDate,
InvoiceTotal = x.InvoiceAmount,
IsApproved = x.IsApproved,
InvoiceStatus = (
x.IsApproved == null ? "Pending" :
x.IsApproved == true ? "Approved" :
x.IsApproved == false ? "Rejected" : "Unknown"
),
InvoicePeriodStartDateText = x.InvoicePeriodStart.ToShortDateString(),
InvoicePeriodEndDateText = x.InvoicePeriodEnd.ToShortDateString(),
InvoicePeriodStartDate = x.InvoicePeriodStart,
InvoicePeriodEndDate = x.InvoicePeriodEnd
}
);
invoices = inefficientEnumerable.ToList();
这里AsEnumerable
用于整个表。所有列都被选中,即使它们不是必需的。
更好的方法
IQueryable<InvoiceDTO> invoicesQuery =
(from a in db.Invoices
where a.Practice_Key == practiceKey.FirstOrDefault()
select new InvoiceDTO
{
InvoiceID = a.InvoiceID,
PracticeShortName = a.Dim_Practice.Short_Name,
InvoiceDate = a.InvoiceDate,
InvoiceTotal = a.InvoiceAmount,
IsApproved = a.IsApproved,
InvoiceStatus = (
a.IsApproved == null ? "Pending" :
a.IsApproved == true ? "Approved" :
a.IsApproved == false ? "Rejected" :"Unknown"
),
InvoicePeriodStartDate = a.InvoicePeriodStart,
InvoicePeriodEndDate = a.InvoicePeriodEnd
});
IEnumerable<InvoiceDTO> betterEnumerable = invoicesQuery.AsEnumerable().
Select(x => new InvoiceDTO
{
InvoiceID = x.InvoiceID,
PracticeShortName = x.PracticeShortName,
InvoiceDate = x.InvoiceDate,
InvoiceTotal = x.InvoiceTotal,
IsApproved = x.IsApproved,
InvoiceStatus = x.InvoiceStatus,
InvoicePeriodStartDateText = x.InvoicePeriodStartDate.ToShortDateString(),
InvoicePeriodEndDateText = x.InvoicePeriodEndDate.ToShortDateString(),
InvoicePeriodStartDate = x.InvoicePeriodStartDate,
InvoicePeriodEndDate = x.InvoicePeriodEndDate
}
);