考虑这段代码:
public List<Clients> GetFilteredClients(DateTime? FromDate = null,
DateTime? ToDate = null,
int? fromLocationType = null,
int? toLocationType = null)
{
Func<Clients, bool> fromDateFilter = f => true;
if (FromDate.HasValue)
{
fromDateFilter = z => z.Insert_Date.Value.Date >= FromDate.Value.Date;
}
Func<Clients, bool> toDateFilter = f => true;
if (ToDate.HasValue)
{
toDateFilter = z => z.Insert_Date.Value.Date <= ToDate.Value.Date;
}
Func<Clients, bool> fromLocationTypeFilter = f => true;
if (fromLocationType.HasValue)
{
fromOrgFilter = z => z.LocationTypeId >= fromLocationType.Value;
}
Func<Clients, bool> toLocationTypeFilter = f => true;
if (toLocationType.HasValue)
{
toLocationTypeFilter = z => z.LocationTypeId <= toLocationType.Value;
}
var filtered = DB_Context.Clients
.Where(fromDateFilter)
.Where(toDateFilter)
.Where(fromLocationTypeFilter)
.Where(toLocationTypeFilter)
.OrderByDescending(k => k.Id)
.Take(1000)
.ToList();
return filtered;
}
我在数据库中有大约 100K 条记录,我只需要满足以下要求的前 1000 条:
.Where(fromDateFilter)
.Where(toDateFilter)
.Where(fromLocationTypeFilter)
.Where(toLocationTypeFilter)
但是执行时间仍然需要大约 10 秒。
知道为什么吗?
最佳答案
您必须使用 Expression<Func<...>>
而不是 Func<...>
.当您使用 Func
, 只有可枚举的方法可以用于可查询的,在这种情况下意味着您首先将所有内容下载到内存中,然后进行过滤。如果你切换到 Expression<...>
,O/RM 将在数据库服务器上进行过滤,而不是在您的应用程序中。
此外,还有更好的方法来完成您正在做的事情。例如,您可以像这样构建条件:
var query = DB_Context.Clients.AsQueryable();
if (FromDate.HasValue) query = query.Where(...);
if (ToDate.HasValue) query = query.Where(...);
...
return query.OrderByDescending(k => k.Id).Take(1000).ToList();
当然,这意味着您使用的任何数据库提供商都必须能够支持您尝试执行的过滤类型 - 您需要查阅文档。
关于c# - 使用 Func 和 OrderByDescending 时 Linq 查询花费的时间太长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33102832/