代码之家  ›  专栏  ›  技术社区  ›  Jim Mitchener

在linq.table.where()中使用可选或子句

  •  2
  • Jim Mitchener  · 技术社区  · 15 年前

    是否有方法使ProjectID在可选块的下面进行检查?我是JavaEE的NET.NET转换,我正在寻找类似于Hibernate标准API的东西。我想简化下面的块,只需要调用一次where()。当我一周前刚开始使用.NET时,我也不确定使用lambda执行where()的性能影响。

    public IQueryable<Project> FindByIdOrDescription(string search)
        {
            int projectID;
            bool isID = int.TryParse(search, out projectID);
    
            IQueryable<Project> projects;
    
            if (isID)
            {
                projects = dataContext.Projects.Where(p => p.ProjectDescription.Contains(search) || p.ProjectID == projectID);
            }
            else
            {
                projects = dataContext.Projects.Where(p => p.ProjectDescription.Contains(search));
            }
    
            return projects;
        }
    
    3 回复  |  直到 12 年前
        1
  •  3
  •   Ruben    15 年前

    如果您正在寻找可选添加 AND xyz 你可以简单地用链子 Where 电话:

    var projects = dataContext.Projects.Where(p => p.ProjectDescription.Contains(search));
    if (isID)
        projects = projects.Where(p => p.ProjectID == projectID);
    

    不幸的是,当你想做一个 OR xyz . 为了使这项工作正常,您需要手工构建一个谓词表达式。 它不漂亮。 一种方法是

    Expression<Func<Project, bool>> predicate = p => p.ProjectDescription.Contains(search);
    if (isID)
    {
        ParameterExpression param = expr.Body.Parameters[0];
        predicate = Expression.Lambda<Func<Project, bool>>(
            Expression.Or(
                expr.Body,
                Expression.Equal(
                    Expression.Property(param, "ProjectID"),
                    Expression.Constant(projectID))),
            param);
    }
    var projects = dataContext.Projects.Where(predicate);
    

    请注意,向现有谓词添加条件比创建初始表达式要多得多,因为我们需要完全重建表达式。(谓词必须始终使用单个参数;使用lambda语法声明两个表达式将创建两个单独的参数表达式对象,每个谓词一个。)请注意,当您对初始谓词使用lambda语法时,C编译器在后台的操作大致相同。

    请注意,如果您习惯了Hibernate的标准API,这看起来可能很熟悉,只是稍微详细一点。


    但是,请注意,一些LINQ实现非常智能,因此以下内容也可能有效:

    var projects = dataContext.Projects.Where(
        p => p.ProjectDescription.Contains(search)
          || (isID && p.ProjectID == projectID));
    

    不过,YMMV也要检查生成的SQL。

        2
  •  1
  •   BFree    15 年前

    直到您第一次真正访问iQuery的元素时,才解析和执行查询。因此,无论您在何处添加了多少个附件(无论如何您都不需要在这里执行这些操作),您都不必担心会多次命中DB。

        3
  •  0
  •   driis    15 年前

    委托/表达式可以“链接”,如下所示(未测试的伪代码):

    Expression<Predicate<Project>> predicate = p => p.ProjectDescription.Contains(search);
    if ( isID ) 
        predicate = p => predicate(p) || p.ProjectID == projectId;
    
    return dataContext.Where(predicate);