【问题标题】:Why are Func<> and Expression<Func<>> Interchangeable? Why does one work in my case?为什么 Func<> 和 Expression<Func<>> 可以互换?为什么在我的情况下工作?
【发布时间】:2012-04-18 11:53:16
【问题描述】:

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

此方法以 Expression 作为参数,有效:

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())。首先,为什么会编译?我的意思是,为什么 Expression 和 Func 可以互换用作参数?那么,为什么 Expression 有效,而 Func 版本只是挂了?

注意:上述方法和这个方法的唯一区别是方法参数(Expression vs. 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();
}

【问题讨论】:

  • 这与答案一起本身就是对“表达式树的意义何在?”的一些很好的回应。问题的风格。 +1 问答

标签: c# oop linq-to-sql generics


【解决方案1】:

Expression 版本调用Queryable.Where 生成一个表达式树,它(当ToList 枚举时)被转换为sql 并在数据库服务器上执行。据推测,数据库服务器将根据过滤条件使用索引,以避免读取整个表。

Func 版本调用 Enumerable.Where(当被 ToList 枚举时)加载整个表(您认为是挂起),然后针对内存中的对象运行过滤条件.

【讨论】:

  • Ahhhhhhhhhhhhh... 不错。完全有道理。谢谢!
猜你喜欢
  • 1970-01-01
  • 2010-10-22
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 2012-01-07
相关资源
最近更新 更多