【问题标题】:Linq IQueryable short circuiting an empty search parameterLinq IQueryable短路一个空的搜索参数
【发布时间】:2010-11-25 15:05:16
【问题描述】:

我有一个使用以下方法的通用存储库

IQueryable<T> GetAllByFilter(Expression<Func<T, bool>> expression);

我现在尝试通过前端提供一种搜索功能,其中一个或多个参数可能已输入或留空。我在为空参数短路表达式时遇到问题。

可以通过在存储库中调用以下示例来演示该问题:

public IEnumerable<Foo> Search(string param)
{
    var filteredFoos = _fooRepository.GetAllByFilter(
          f => string.IsNullOrEmpty(param) || f.Something == param );

    return filteredFoos.ToList(); // throws exception
}

如果paramnull,则使用ToList() 枚举查询会引发System.NullReferenceException

我既不明白这一点,也不知道如何解决它,所以任何指针表示赞赏。谢谢。

更新: 为了响应下面的 cmets,我添加了一个空检查。我的实际代码现在是这样的

var test1 = _repository.GetAllByFilter(
     r => r != null && 
         (string.IsNullOrEmpty(param) 
              || (r.Field != null && r.Field.IndexOf(param.Trim()) != -1)));

var test2 = test1.ToList(); // exception here

我仍然没有看到问题出在哪里。

编辑:回应评论,通用存储库GetAllByFilter 代码:

public IQueryable<T> GetAllByFilter(Expression<Func<T, bool>> expression)
{
    return _dataContext.GetTable<T>().Where(expression);
}

请注意,如果我运行一个简单的 GetAll 查询

public IQueryable<T> GetAll()
 {
     return _dataContext.GetTable<T>();
 }

在同一张表上,没有null 记录被返回(如预期的那样)。

【问题讨论】:

  • 听起来不对,你确定没有'f'参数为空,'f.Something'抛出异常的情况吗?
  • 我不这么认为,只要传入一个非空字符串作为参数,查询就可以正常运行。我不明白 f 怎么可能是空的?
  • @fearofawhackplanet - f 为空的唯一方法是_fooRepository 返回一个空项目。你确定不是这样吗?
  • 进一步更新;我没有最模糊的想法。
  • 我们能看到GetAllByFilter()的代码吗?

标签: c# linq-to-sql .net-3.5 expression-trees short-circuiting


【解决方案1】:

保持简单:

public IEnumerable<Foo> Search(string param)
{
    if (string.IsNullOrEmpty(param))
    {
        return this.fooRepository.GetAll().ToArray();
    }

    return this.fooRepository.GetAllByFilter(o => o.Field.Contains(param.Trim())).ToArray();
}

【讨论】:

  • 创建问题时没有“GetAll()”方法。有点天真地认为这是一个单人项目,您可以在其中修改应用程序的所有部分。
【解决方案2】:

蛋糕。

    public IEnumerable<Foo> Search(string param)
    {
        Expression<Func<Foo, bool>> shortCircuit = a => true;
        Expression<Func<Foo, bool>> normal = a => a.Something == param;

        var filteredFoos = _fooRepository.GetAllByFilter(
            string.IsNullOrEmpty(param) ? shortCircuit : normal);

        return filteredFoos.ToList(); // no more exception.
    }

您只需要记住,您不能将任何内容放入那些 IQueryable 方法中并期望它们能够理解。您可能可以将 shortCircuit 表达式设为静态。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多