【问题标题】:How to create condtional lambda expression for date ranges?如何为日期范围创建条件 lambda 表达式?
【发布时间】:2016-07-18 12:59:56
【问题描述】:

在我的 ASP.net MVC 项目中,我有一个包含 7 个搜索变量的搜索表单。它们都不是强制性的,但是,应该至少选择一个来执行搜索操作,如图所示。

在这种情况下使用 lambda 表达式执行搜索的最佳方法是什么,因为用户可以选择任何搜索参数组合?目前,我正在使用一长串“if-else if”结构并为每个结构编写单独的 lambda 表达式。有没有更好/更有效的方法?

更新 1: 这只是条件的一半,现在我被告知,即使是三个日期标准中的每一个的“日期”都是可选的,这将进一步增加检查列表。这是标准的做法吗?

IEnumerable<MyRecord> Request = null;
        if (!status.Equals(""))
        {
            if (deliveryDateFrom == null && caseDateFrom == null && pickupDateFrom == null)
            {
                //only request status
                Request = GetRecord("EquipRequest")
                    .Where(r => r.Status == status);                            
            }
            else if (deliveryDateFrom != null && caseDateFrom == null && pickupDateFrom == null)
            {
                // request status and delivery date
                Request = GetRecord("EquipRequest")
                    .Where(r => r.Status == status && (r.DeliveryDate >= deliveryDateFrom && r.DeliveryDate <= deliveryDateTo));
            }
            else if (deliveryDateFrom == null && caseDateFrom != null && pickupDateFrom == null)
            {
                // request status and case date 
                Request = GetRecord("EquipRequest")
                    .Where(r => r.Status == status && (r.CaseDate >= caseDateFrom && r.CaseDate <= caseDateTo));
            }
            else if (deliveryDateFrom == null && caseDateFrom == null && pickupDateFrom != null)
            {
                // request status and pickup date
                Request = GetRecord("EquipRequest")
                    .Where(r => r.Status == status && (r.PickupDate >= pickupDateFrom && r.PickupDate <= pickupDateTo));  
            }
            else if (deliveryDateFrom != null && caseDateFrom != null && pickupDateFrom == null)
            {
                // request status, delivery date and case date
                Request = GetRecord("EquipRequest")
                    .Where(r => r.Status == status && (r.DeliveryDate >= deliveryDateFrom && r.DeliveryDate <= deliveryDateTo)
                    && (r.CaseDate >= caseDateFrom && r.CaseDate <= caseDateTo));  
            }
            else if (deliveryDateFrom != null && caseDateFrom == null && pickupDateFrom != null)
            {
                // request status, delivery date and pickup date
                Request = GetRecord("EquipRequest")
                    .Where(r => r.Status == status && (r.DeliveryDate >= deliveryDateFrom && r.DeliveryDate <= deliveryDateTo)
                    && (r.PickupDate >= pickupDateFrom && r.PickupDate <= pickupDateTo)); 
            }
            else if (deliveryDateFrom == null && caseDateFrom != null && pickupDateFrom != null)
            {
                // request status, case date and pickup date
                Request = GetRecord("EquipRequest")
                    .Where(r => r.Status == status && (r.CaseDate >= caseDateFrom && r.CaseDate <= caseDateTo)
                    && (r.PickupDate >= pickupDateFrom && r.PickupDate <= pickupDateTo)); 
            }
            else if (deliveryDateFrom != null && caseDateFrom != null && pickupDateFrom != null)
            {
                // request status, delivery date, case date and pickup date
                Request = GetRecord("EquipRequest")
                    .Where(r => r.Status == status && (r.DeliveryDate >= deliveryDateFrom && r.DeliveryDate <= deliveryDateTo)
                    && (r.CaseDate >= caseDateFrom && r.CaseDate <= caseDateTo)
                    && (r.PickupDate >= pickupDateFrom && r.PickupDate <= pickupDateTo));
            }                
        }

【问题讨论】:

  • 您只需要 6 个 if 语句(每个条件一个)(并且不需要 else if
  • 向我们展示(至少部分)您的代码,以便我们提供帮助。
  • 请发布您的代码以提供更好的解决方案。
  • var query = GetRecord("EquipRequest"); if (status != null) { query = query.Where(x =&gt; x.Status == status); } if (deliveryDateFrom != null) { query.Where(x =&gt; x.DeliveryDate &gt;= deliveryDateFrom); } 等(每个条件一个)
  • @SJaka 如果它调用 Web 服务来获取所有记录然后过滤,这可能会对性能产生巨大影响。最好在服务中过滤您的结果并返回最少的数据。

标签: c# asp.net asp.net-mvc asp.net-mvc-4 lambda


【解决方案1】:

你可以做的是使用如下函数:

public static IEnumerable<TSource> WhereIf<TSource>(this IEnumerable<TSource> source, bool condition, Func<TSource, bool> predicate)
{
    return condition ? source.Where(predicate) : source;
}

如果 bool 为真,它将通过您的 lambda 表达式缩小范围,如果为假,它将继续。

并像这样使用它:

var whatever = GetRecord("EquipRequest")
    .Where(r.Status == status)
    .WhereIf(deliveryDateFrom != null, r => r.DeliveryDate >= deliveryDateFrom)
    .WhereIf(deliveryDateTo != null, r => r.DeliveryDate <= deliveryDateTo)
    .WhereIf(caseDateFrom != null, r => r.CaseDate >= caseDateFrom)
    .WhereIf(caseDateTo != null, r => r.CaseDate <= caseDateTo)
    .WhereIf(pickupDateFrom != null, r => r.PickupDate >= pickupDateFrom)
    .WhereIf(pickupDateTo != null, r => r.PickupDate <= pickupDateTo)

以此类推

【讨论】:

    【解决方案2】:

    首先我建议你获取LinqPad,学习它,如果你想尝试这样的东西。

    然后编写类似这样的 LinqPad 脚本并运行它以使您的 Linq 语句正确:

    public class SearchViewModel {
        public DateTime DeliveryDateFrom {get; set;}
        public DateTime DeliveryDateTo {get; set;}
        public DateTime CaseDateFrom {get; set;}
        public DateTime CaseDateTo {get; set;}
        public DateTime PickupDateFrom {get; set;}
        public DateTime PickupDateTo {get; set;}
    };
    
    
    
    public class Data {
        public DateTime DeliveryDate {get; set;}
        public DateTime CaseDate {get; set;}
        public DateTime PickupDate {get; set;}
    };
    
    void Main()
    {
        var model = new SearchViewModel();  // insert your model stuff here
        // you can use LinqPad to hook up directly to your project DBContext dll here
        var dataBase = new List<Data>() { 
            new Data() { DeliveryDate = DateTime.Now, CaseDate = DateTime.Now, PickupDate = DateTime.Now }
        };  
    
        // experiment with Linq statement here
        var result = dataBase.Where(x =>
            (model.DeliveryDateFrom >=  x.DeliveryDate && model.DeliveryDateTo <=  x.DeliveryDate) &&
            (model.CaseDateFrom >=  x.CaseDate && model.CaseDateTo <=  x.CaseDate) &&
            (model.PickupDateFrom >=  x.PickupDate && model.PickupDateTo <=  x.PickupDate)
        );
    
        result.Dump();
    }
    

    【讨论】:

    • mage 感谢您的快速响应。我可以编写 lambda 和 linq 表达式。但是,我担心涵盖所有可能情况所需的 if 检查数量。我已经更新了问题。
    【解决方案3】:

    您可以链接 where 子句。

    IEnumerable<MyRecord> query = GetRecord("EquipRequest");
    if (!status.Equals(""))
    {
        if (deliveryDateFrom.HasValue) 
            query = query.Where(x => x.DeliveryDate >= deliveryDateFrom);
        if (deliveryDateTo.HasValue) 
            query = query.Where(x => x.DeliveryDate <= deliveryDateTo);
    }
    IEnumerable<MyRecord> result = query.ToList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-06
      相关资源
      最近更新 更多