Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过lambdas为where构造表达式_C#_Lambda_Entity Framework 4 - Fatal编程技术网

C# 通过lambdas为where构造表达式

C# 通过lambdas为where构造表达式,c#,lambda,entity-framework-4,C#,Lambda,Entity Framework 4,形势 我有一个接受POCO的方法。此POCO如下所示 private class SearchCriteria { public string name get;set; public string age get;set; public string talent get;set; .. .... } 该方法基本上有一个对db的查询,该查询使用上述条件 public void query(SearchCriteria

形势

我有一个接受POCO的方法。此POCO如下所示

    private class SearchCriteria
    {
      public string name get;set;
      public string age get;set;
      public string talent get;set;
    .. 
.... 
     }
该方法基本上有一个对db的查询,该查询使用上述条件

public void query(SearchCriteria crit)
{
  if(crit.name!=null && crit.age!=null && crit.talent !=null)
   {
     dbContext.Students.Where(c=>c.name ==crit.name &&    c.age==crit.age...)
   }
  else if(crit.name !=null && crit.age!=null)
  {
  }
  else if(....
  {
  }
正如您所看到的,上面有一个明确的问题,在中,如果有大量的条件,我将不得不写很多if-else,以便从where子句中删除特定的参数

可能的解决方案是什么

事实上,我对lambda expressions的世界还很陌生,但我相信我们一定有一个设施,可以让我们做下面的事情

dbContext.Students.WhereprocessCriteriasearchCriteriaPOCO


你们能带我到正确的方向吗?。谢谢

也许我遗漏了一些东西,因为代码示例不是我见过的最清晰的,但是对于您的具体示例,我认为以下内容应该可以:

dbContext.Students.Where(c => (crit.name == null || crit.name == c.name) &&
    (crit.age == null || crit.age == c.age) &&
    (crit.talent == null || crit.talent == c.talent));
不需要链接一堆if语句


对于更复杂的场景,您可能更喜欢类似

的内容,因为代码示例不是我见过的最清晰的,但对于您的特定示例,我认为以下内容应该可以:

dbContext.Students.Where(c => (crit.name == null || crit.name == c.name) &&
    (crit.age == null || crit.age == c.age) &&
    (crit.talent == null || crit.talent == c.talent));
不需要链接一堆if语句


对于更复杂的场景,您可能更喜欢类似于

的模式,您可以使用如下模式:

dbContext.Students.Where(c=>(crit.name == null || c.name ==crit.name) && ...)

如果搜索条件为空,则会给出一个始终为真的子表达式。

您可以使用如下模式:

dbContext.Students.Where(c=>(crit.name == null || c.name ==crit.name) && ...)

如果搜索条件为空,则会给出一个始终为真的子表达式。

获取一个可查询项,然后继续向其添加where子句。这样,您只需要测试每个可能的条件一次,并且只生成绝对需要的where子句的数量

IQueryable<Student> q = dbContext.Students.AsQueryable();

if (crit.name != null)
    q = q.Where(c => c.name == crit.name);

if (crit.age != null)
    q = q.Where(c => c.age== crit.age);

获取一个queryable,然后继续向其中添加where子句。这样,您只需要测试每个可能的条件一次,并且只生成绝对需要的where子句的数量

IQueryable<Student> q = dbContext.Students.AsQueryable();

if (crit.name != null)
    q = q.Where(c => c.name == crit.name);

if (crit.age != null)
    q = q.Where(c => c.age== crit.age);

让我首先说,这个答案使用了与@PhillWright相同的基本思想。它只是将其封装在一个扩展方法中,该扩展方法为您应用此模式,并允许您拥有一个可读性良好的语法

public static class SearchExtensions
{
    public static IQueryable<Student> Query(this SearchCriteria criteria, IQueryable<Student> studentQuery)
    {
        return studentQuery
            .Match(criteria.name, (student) => student.name == criteria.name)
            .Match(criteria.age, (student) => student.age == criteria.age)
            .Match(criteria.talent, (student) => student.talent == criteria.talent);
            // add expressions for other fields if needed.
    }

    private static IQueryable<Student> Match<T>(
        this IQueryable<Student> studentQuery,
        T criterionValue,
        Expression<Func<Student, bool>> whereClause) where T : class
    {
        // only use the expression if the criterion value is non-null.
        return criterionValue == null ? studentQuery : studentQuery.Where(whereClause);
    }
}

让我首先说,这个答案使用了与@PhillWright相同的基本思想。它只是将其封装在一个扩展方法中,该扩展方法为您应用此模式,并允许您拥有一个可读性良好的语法

public static class SearchExtensions
{
    public static IQueryable<Student> Query(this SearchCriteria criteria, IQueryable<Student> studentQuery)
    {
        return studentQuery
            .Match(criteria.name, (student) => student.name == criteria.name)
            .Match(criteria.age, (student) => student.age == criteria.age)
            .Match(criteria.talent, (student) => student.talent == criteria.talent);
            // add expressions for other fields if needed.
    }

    private static IQueryable<Student> Match<T>(
        this IQueryable<Student> studentQuery,
        T criterionValue,
        Expression<Func<Student, bool>> whereClause) where T : class
    {
        // only use the expression if the criterion value is non-null.
        return criterionValue == null ? studentQuery : studentQuery.Where(whereClause);
    }
}

妮特:我要么使用var,要么删除.AsQueryable。如果显式指定类型,则后者没有值。菲尔,如果连续的IFs被执行,它会不会取代q中的值。只有最后一个where子句在q中。还是所有成功的国际单项体育联合会都会积累各自的where子句?@MuhammadAhmedAbuTalib the q.where。。。返回包含where子句表达式的新IQueryable实例。您可以链接where expressions.Alex,这意味着如果上述代码段中的两个ifs都为true,那么我们将有两个数据库查询,对吗。因此,如果我们有十个if,将在DB服务器上来回运行十次?Nit:我要么使用var,要么删除.AsQueryable。如果显式指定类型,则后者没有值。菲尔,如果连续的IFs被执行,它会不会取代q中的值。只有最后一个where子句在q中。还是所有成功的国际单项体育联合会都会积累各自的where子句?@MuhammadAhmedAbuTalib the q.where。。。返回包含where子句表达式的新IQueryable实例。您可以链接where expressions.Alex,这意味着如果上述代码段中的两个ifs都为true,那么我们将有两个数据库查询,对吗。因此,如果我们有十个如果,将与数据库服务器来回,十次?这真是天才和整洁。我真的很羡慕你的天赋:D。这真的是天才和整洁。我真的很羡慕你的天赋:D。如果有任何答案充分解决了你的问题,你能选择它作为答案吗,或者,如果你自己找到了更好的方法,请将其作为答案发布。如果任何答案充分解决了你的问题,请选择它作为答案,或者,如果你自己找到了更好的方法,请将其作为答案发布。