为什么 Func<> 和 Expression> 可以互换?为什么一个在我的情况下有效

本文关键字:为什么 Func 一个 情况下 有效 我的 Expression 互换 | 更新日期: 2023-09-27 18:30:06

我有一个数据访问类,花了我一段时间才开始工作。对于我的应用程序,我需要获取不同类型的 SQL Server 表,其中 WHERE 子句仅因列名而异:某些列是read_time列,其他列是 ReadTime,其他列是 LastModifiedTime。所以我想我会传入 WHERE 子句,这样我就不需要为 50 个不同的表创建一个新方法。它看起来很简单,而且有效,但我不明白什么。

此方法以表达式<>作为参数,工作:

internal List<T> GetObjectsGreaterThanReadTime<T>(Expression<Func<T, bool>> whereClause) where T : class
{
    Table<T> table = this.Database.GetTable<T>();
    IEnumerable<T> objects = table.Where(whereClause);
    return objects.ToList();
}

现在,我以这种方式(下面(尝试了一段时间,它只会挂在最后一行(ToList(((。首先,为什么要编译?我的意思是,为什么表达式和 Func 可以互换用作参数?那么,为什么表达式有效,而 Func 版本只是挂起?

注意:上述方法与此方法之间的唯一区别是方法参数(表达式与函数(。

internal List<T> GetObjectsGreaterThanReadTime<T>(Func<T, bool> whereClause) where T : class
{
    Table<T> table = this.Database.GetTable<T>();
    IEnumerable<T> objects = table.Where(whereClause);
    return objects.ToList();
}

为什么 Func<> 和 Expression<Func<>> 可以互换?为什么一个在我的情况下有效

表达式版本调用Queryable.Where,生成表达式树,该表达式树(当由ToList枚举时(被转换为SQL并在数据库服务器上执行。 据推测,数据库服务器将利用基于筛选条件的索引,以避免读取整个表。

Func 版本调用Enumerable.Where它(当由 ToList 枚举时(加载整个表(您认为是挂起(,然后针对内存中对象运行筛选条件。