简体   繁体   English

Linq where子句“如果item不为null,则求值,否则,获取所有数据”

[英]Linq where clause “if item is not null, evaluate, otherwise, get all data”

I'm trying to implement a filter form on a web client which could have any number of items either filled out or empty. 我正在尝试在Web客户端上实现一个过滤器表单,该表单可以具有任意数量的项目,这些项目可以填写或为空。 My WebAPI method will take a model that is all of the properties of the form, it would be like: 我的WebAPI方法将采用包含表单所有属性的模型,就像这样:

RequisitionType (enum: RequisitionType.RequisitionedBy, RequisitionType.CreatedBy)
Vendor (string or null)
Plant (string or null)
CompanyCode (string or null)
CreatedFrom (datetime)
CreatedTo (datetime)

How could I implement a linq query without have many crazy if (condition) { filter } ? 我如何在没有很多if (condition) { filter }实现linq查询?

I've tried something like this, where I first check if the filter has a value and if it does I will compare the field to that value, otherwise I'll compare the field to itself, but the compiler isn't allowing that. 我已经尝试过类似的方法,在该方法中,我首先检查过滤器是否有值,如果有,我将字段与该值进行比较,否则,我将字段与自身进行比较,但是编译器不允许这样做。

In the example below, model is what's passed to the controller from the client. 在下面的示例中, model是从客户端传递到控制器的model

var data =  logic.GetPurchaseReqs()
            .Where(pr => {
                model.RequisitionType == RequisitionType.RequisitionedBy ? pr.PrReqId.ToUpper() == model.Username.ToUpper() : pr.PrReqId.ToUpper() == pr.PrReqId.ToUpper()
                && model.RequisitionType == RequisitionType.CreatedBy ? pr.PrCreId.ToUpper() == model.Username.ToUpper() : pr.PrCreId.ToUpper() == pr.PrCreId.ToUpper()
                && model.Vendor != null ? pr.Vendor == model.Vendor : pr.Vendor == pr.Vendor
                [etc...]
            })
            .ToList();

I believe the easiest way to simplify this would be: 我认为最简单的方法是:

logic.GetPurchaseReqs()
     .Where(pr => model.RequisitionType != RequisitionType.RequisitionedBy || pr.PrReqId.ToUpper() == model.Username.ToUpper())
     .Where(pr => model.RequisitionType != RequisitionType.CreatedBy || pr.PrCreId.ToUpper() == model.Username.ToUpper())
     .Where(pr => model.Vendor == null || pr.Vendor == model.Vendor)
     //[...]
     .ToList();

Note that adding several Where clauses introduces miniscule overhead (just the processing power required for the JIT to call a function), but IMHO improves readability. 请注意,添加几个Where子句会带来很小的开销(恰好是JIT调用函数所需的处理能力),但是IMHO可以提高可读性。

For readability and since it is almost the same amount of code I would definitely go with the if(condition) solution. 为了提高可读性,并且由于它几乎是相同数量的代码,我肯定会使用if(condition)解决方案。

var data = logic.GetPurchaseReqs(); //.AsEnumerable() migt be needed here

if(model.RequisitionType == RequisitionType.RequisitionedBy)
  data = data.Where(pr => pr.PrReqId.ToUpper() == model.Username.ToUpper())

if(model.Vendor != null)
  data = data.Where(pr => pr.Vendor == model.Vendor);

if(model.CompanyCode != null)
  data = data.Where(pr => pr.CompanyCode == model.CompanyCode);

...

Not completely following what you are trying to do but based on your title: 不是完全遵循您的尝试,而是基于标题:

var data = logic.GetPurchaseReqs();

if(condition)
{
    data = data.Where(pr => pr.... etc
}

var result = data.ToList();

This is what I would program it as. 这就是我要编程的方式。 Note the lack of brackets and the way I handled the requisition type. 请注意缺少方括号以及我处理请购单类型的方式。 This assumes that requisition type cannot be null...if it CAN...then you have to add a 3rd condition || model.RequisitionType == null 这假定申请单类型不能为空...如果可以的话...那么您必须添加第三个条件|| model.RequisitionType == null || model.RequisitionType == null . || model.RequisitionType == null Otherwise, each condition you check gets added on as another && (condition != null ? conditionCheck : true) 否则,您检查的每个条件都会作为另一个&& (condition != null ? conditionCheck : true)添加&& (condition != null ? conditionCheck : true)

var data = logic.GetPruchaseReqs().Where(pr =>
    ((model.RequisitionType == RequisitionType.RequisitionedBy && pr.PrReqId.Equals(model.Username, StringComparison.InvariantCultureIgnoreCase)) || (model.RequisitionType == RequisitionType.CreatedBy && pr.PrCreId.Equals(model.Username, StringComparison.InvariantCultureIgnoreCase))) 
    && (model.Vendor != null ? pr.Vendor.Equals(model.Vendor) : true) 
    && (condition != null ? conditionCheck : true)).ToList();

The goal is to setup the right side of the => to evaluate down to a single boolean true/false. 目标是设置=>的右侧,以求出一个布尔值true / false。 You should be able to evaluate the statement for any given value of (pr) and get either true or false. 您应该能够为(pr)的任何给定值评估该语句,并获得true或false。

The best solution would be to create yourself an extension method for linq. 最好的解决方案是为linq创建一个扩展方法。 It will take in a conditional statment and a where expression, and if the condition is true it will use the where expression, else it will skip it. 它会接受一个条件语句和一个where表达式,如果条件为true,它将使用where表达式,否则它将跳过它。 This can dramatically clean up your code, eliminating the need for if statements. 这可以极大地清理您的代码,而无需if语句。

public static class LinqExtension
{
    public static IQueryable<T> Where<T>(this IQueryable<T> query, bool condition, Expression<Func<T, bool>> whereClause)
    {
        if (condition)
        {
            return query.Where(whereClause);
        }
        return query;
    }
}

Now you can do conditional where statements without using if statements. 现在,您可以执行条件where语句,而无需使用if语句。

var data = logic.GetPurchaseReqs()
                .Where(model.RequisitionType == RequisitionType.RequisitionedBy, pr => pr.PrReqId.ToUpper() == model.Username.ToUpper())
                .Where(model.Vendor != null, pr => pr.Vendor == model.Vendor)
                .Where(model.CompanyCode != null, pr => pr.CompanyCode == model.CompanyCode);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM