系统.传递给linq where方法而不枚举的函数
本文关键字:枚举 函数 方法 where linq 系统 | 更新日期: 2023-09-27 18:02:25
我有一个方法,我试图返回所有默认客户地址与匹配的性别。我希望能够通过在系统中传递一点一点地建立过滤查询。
var emailAddresses = new List<string>();
// get all customers.
IQueryable<Customer> customersQ = base.GetAllQueryable(appContext).Where(o => o.Deleted == false);
// for each customer filter, filter the query.
var genders = new List<string>() { "C" };
Func<Customer, bool> customerGender = (o => genders.Contains(o.Addresses.FirstOrDefault(a => a.IsDefaultAddress).Gender));
customersQ = customersQ.Where(customerGender).AsQueryable();
emailAddresses = (from c in customersQ
select c.Email).Distinct().ToList();
return emailAddresses;
但是这个方法为每个地址调用数据库(8000次),速度非常慢。
但是如果我替换这两行
Func<Customer, bool> customerGender = (o => genders.Contains(o.Addresses.FirstOrDefault(a => a.IsDefaultAddress).Gender));
customersQ = customersQ.Where(customerGender).AsQueryable();
一行
customersQ = customersQ.Where(o => genders.Contains(o.Addresses.FirstOrDefault(a => a.IsDefaultAddress).Gender)).AsQueryable();
然后查询只调用一次数据库,速度非常快。
我的问题是为什么这有区别?我如何使第一个方法只调用数据库一次工作?
使用expression代替Func:
Expression<Func<Customer, bool>> customerGender = (o =>
genders.Contains(o.Addresses.FirstOrDefault(a => a.IsDefaultAddress).Gender));
customersQ = customersQ.Where(customerGender).AsQueryable();
当使用简单的Func
委托时,则调用Enumerable
的Where
扩展。因此,所有数据都进入内存,在内存中对其进行枚举,并对每个实体执行lambda。并且你有很多调用数据库。
另一方面,当您使用表达式时,则调用Queryable
的Where
扩展,将表达式转换为SQL查询。这就是为什么在第二种情况下使用单个查询(如果使用就地lambda,则将其转换为表达式)。