【问题标题】:The best way to build Dynamic LINQ query构建动态 LINQ 查询的最佳方式
【发布时间】:2010-10-18 17:27:43
【问题描述】:

您好,我正在寻找编写动态 LINQ 查询的最佳方法。

我有一个类似的功能

public IQueryable<Student> FindByAllStudents(int? id, string Name, int? CourseID, bool? IsActive) // like this way, all field values are passed
    {    
        // code for compairision
        return db.Student;
    }

我们也可以写 db.Students.where(predicate)

类似的查询

var students = from s in db.students where s.Name.Contains(Name)
                s.ID.Equals(id)
                //and so on....

如果我不传递 ID(即 Null),这个方法会起作用吗? 是所有数据类型的正确方法吗?

关键是函数可以将所有空值作为select * from语句等价的参数。

谁能帮助我使用示例代码构建最佳查询?

【问题讨论】:

    标签: asp.net linq


    【解决方案1】:

    好的,你想要什么并不完全清楚,但如果你试图只为非空参数添加 where 子句,你可以这样做:

    public IQueryable<Student> FindByAllStudents
        (int? id, string name, int? courseID, bool? isActive)
    {    
        IQueryable<Student> query = db.Student;
        if (id != null)
        {
            query = query.Where(student => student.ID == id.Value);
        }
        if (name != null)
        {
            query = query.Where(student => student.Name.Contains(name));
        }
        if (courseID != null)
        {
            query = query.Where(student => student.CourseID == courseID.Value);
        }
        if (isActive != null)
        {
            query = query.Where(student => student.IsActive == isActive.Value);
        }
        return query;
    }
    

    我还没有尝试过,并且 可能 LINQ to SQL 会被代码弄糊涂以查找可空值类型的值。您可能需要编写如下代码:

        if (courseID != null)
        {
            int queryCourseID = courseID.Value;
            query = query.Where(student => student.CourseID == queryCourseID);
        }
    

    不过还是先试试更简单的形式还是值得的 :)

    当然,这一切都会让人有些恼火。一个有用的扩展方法可以让生活更简洁:

    public static IQueryable<TSource> OptionalWhere<TSource, TParameter>
        (IQueryable<TSource> source,
         TParameter? parameter, 
         Func<TParameter, Expression<Func<TSource,bool>>> whereClause)
        where TParameter : struct
    {
        IQueryable<TSource> ret = source;
        if (parameter != null)
        {
            ret = ret.Where(whereClause(parameter.Value));
        }
        return ret;
    }
    

    然后你会像这样使用它:

    public IQueryable<Student> FindByAllStudents
        (int? id, string name, int? courseID, bool? isActive)
    {    
        IQueryable<Student> query = db.Student
            .OptionalWhere(id, x => (student => student.ID == x))
            .OptionalWhere(courseID, x => (student => student.CourseID == x))
            .OptionalWhere(isActive, x => (student => student.IsActive == x));
        if (name != null)
        {
            query = query.Where(student => student.Name.Contains(name));
        }
        return query;
    }
    

    如果您不太习惯使用这样的高阶函数,可能会让人感到困惑,因此,如果您不做很多这样的查询,您可能希望坚持使用更长但更简单的代码。

    【讨论】:

    • 谢谢!对于第一个解决方案,我们还可以使用 if(id.HasValue) { 而不是使用 id.Value}
    • 你能指导我使用全文搜索吗?
    • 使用 HasValue 等同于使用 != null。恐怕我不知道在 LINQ 中使用全文搜索。
    • 喜欢 Jon 的扩展方法! Linq + 全文搜索在这里讨论:stackoverflow.com/questions/224475/…
    • 如果可以的话,对此稍作评论,我在让它与字符串一起工作时遇到了问题,因为字符串已经可以为空(据我所知,它是一个引用类型而不是结构 - 如果我有那是正确的)。刚刚又看了一遍代码,我可以看到你是单独查询名字的——可能是因为这个限制?
    猜你喜欢
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多