作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个方法可以尝试返回所有具有匹配性别的默认客户地址。我希望能够通过将 System.Func 方法传递给 where 子句来一点一点地构建过滤查询。
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<Customer, bool>> customerGender = (o =>
genders.Contains(o.Addresses.FirstOrDefault(a => a.IsDefaultAddress).Gender));
customersQ = customersQ.Where(customerGender).AsQueryable();
当您使用简单的 Func
委托(delegate)时,然后是 Enumerable
的 Where
扩展名叫做。因此,所有数据都进入内存,在内存中枚举并为每个实体执行 lambda。而且你有很多对数据库的调用。
另一方面,当您使用表达式时,Where
Queryable
的扩展名被调用,表达式被转换成SQL查询。这就是为什么您在第二种情况下只有一个查询(如果您使用就地 lambda,它会转换为表达式)。
关于c# - System.Func 传递给 linq where 方法而不枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15225205/
我是一名优秀的程序员,十分优秀!