系统.传递给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();

然后查询只调用一次数据库,速度非常快。

我的问题是为什么这有区别?我如何使第一个方法只调用数据库一次工作?

系统.传递给linq where方法而不枚举的函数

使用expression代替Func:

Expression<Func<Customer, bool>> customerGender = (o => 
   genders.Contains(o.Addresses.FirstOrDefault(a => a.IsDefaultAddress).Gender));
customersQ = customersQ.Where(customerGender).AsQueryable();

当使用简单的Func委托时,则调用EnumerableWhere扩展。因此,所有数据都进入内存,在内存中对其进行枚举,并对每个实体执行lambda。并且你有很多调用数据库。

另一方面,当您使用表达式时,则调用QueryableWhere扩展,将表达式转换为SQL查询。这就是为什么在第二种情况下使用单个查询(如果使用就地lambda,则将其转换为表达式)。