Linq IQueryable短路空搜索参数

时间:2010-11-25 15:05:17

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

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

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
}

如果ToList()System.NullReferenceException,那么使用param枚举查询会引发null

我既不理解这一点,也不知道如何修复它,所以任何指针都会受到赞赏。谢谢。

更新:为了回应下面的评论,我添加了一个空检查。我的实际代码现在看起来像这样

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条记录(按预期方式)。

2 个答案:

答案 0 :(得分:2)

保持简单:

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();
}

答案 1 :(得分:0)

饼。

    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表达式设置为静态。