C# LINQ 中的 Where 谓词

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2305438/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 01:14:55  来源:igfitidea点击:

Where Predicates in LINQ

c#linq

提问by JustAProgrammer

How can I specify conditions in Where predicates in LINQ without getting null reference exceptions. For instance, if qis an IQueryable how can I do like:

如何在 LINQ 中的 Where 谓词中指定条件而不会出现空引用异常。例如,如果q是一个 IQueryable 我该怎么做:

Expression<Func<ProductEntity,bool>> predicate = p => !search.CategoryId.HasValue || (search.CategoryId.HasValue && search.CategoryId == p.CategoryId);

var q2 = q.Where(predicate);

Here searchis an object that holds possible search conditions that may or may not be set like search.CategoryId might not be set but if it is I want to get the products that are set by that condition.

search是一个保存可能的搜索条件的对象,这些条件可能会或可能不会像 search.CategoryId 那样设置,但如果是这样,我想获取由该条件设置的产品。

When I do this I get null reference exceptions.

当我这样做时,我得到空引用异常。

采纳答案by Johannes Rudolph

You can use the null-coalescing operator??to replace a possible null value with a default value. The following sets tries to match the search.Category if it exists or simply creates an "always true" expression. This will be optimized by any good Linq query provider (e.g. LinqToSql).

您可以使用空合并运算符??将可能的空值替换为默认值。以下集合尝试匹配 search.Category 如果它存在或只是创建一个“始终为真”的表达式。这将由任何好的 Linq 查询提供程序(例如 LinqToSql)进行优化。

Expression<Func<ProductEntity,bool>> predicate = p => (search.CategoryId ?? p.CategoryId) == p.CategoryId);

var q2 = q.Where(predicate);

Another possibility would be to dynamically compose a query predicate using PredicateBuilder. That's the way I do it for searches with a similar pattern as you use:

另一种可能性是使用PredicateBuilder动态组合查询谓词。这就是我使用与您使用的模式类似的搜索方式进行的搜索:

var predicate = PredicateBuilder.True<Order>();

if (search.OrderId))
{
   predicate = predicate.And(a => SqlMethods.Like(a.OrderID, search.OderID);  
}
// ...
var results = q.Where(predicate);

回答by Marc Gravell

Let's dissect the line:

让我们剖析一下这条线:

Expression<Func<ProductEntity,bool> predicate = p => !search.CategoryId.HasValue
       || (search.CategoryId.HasValue && search.CategoryId == p.CategoryId)
var q2 = q.Where(predicate);

So how many ways can we get nullproblems?

那么我们有多少种方式会遇到null问题呢?

  • search(your "captured" variable) could be null
  • pcould be null, meaning there is a nullin the list
  • you've handledthe case of search.CategoryIdbeing null(Nullable<T>)
  • but maybe p.CategoryId(the category on a record in the list) is null(Nullable<T>) - however, I'm not sure that this would cause a NullReferenceException
  • q(the list / source) could be null
  • search(您的“捕获”变量)可能是 null
  • p可能为空,意味着null列表中有一个
  • 处理的情况下search.CategoryIdnullNullable<T>
  • 但也许p.CategoryId(列表中记录的类别)是null( Nullable<T>) - 但是,我不确定这会导致NullReferenceException
  • q(列表/来源)可能是 null

So: out of 5 options you've eliminated 1; look at the other 4? There is alsothe definite possibility that the issue is caused by something invisible not shown in the code; for example the getcould be:

所以:在 5 个选项中你已经消除了 1 个;看看其他4个?有了一定的可能性问题是由代码未显示看不见的东西造成的; 例如get可能是:

public int? CategoryId {
    get {return innerObject.CategoryId;}
}

and innerObjectcould be null; if you eliminate the other 4 (pretty easy to do), look at at this one as a last resort.

并且innerObject可能是null;如果您消除其他 4 个(很容易做到),请将此作为最后的手段。