Linq where clause with multiple conditions

2019-06-20 07:04发布

问题:

this method returns generic list but it has multiple condition to get select. I'm just writing this using if - else if -else if.... so many if else i mean Is there a shorter way to do this? Thank you.

    public List<ProductReqNoDate> GetRequestsQuery(string departmant, int reqStateID, string firstDate, string lastDate)
    {
        var db = new requestsDBEntities();
        var listPrn = new List<ProductReqNoDate>();
        if (!string.IsNullOrEmpty(departmant))
        {
            return  (from r in db.requests
                       where r.departmant== departmant
                       select new ProductReqNoDate
                       {
                           departmant= r.departmant,
                           reqNo = r.reqNo ,
                           reqDate = r.reqDate ,
                           prdctName= stringCutter((from p in db.products where p.reqNo == r.reqNo select p.prdctName).FirstOrDefault())
                       }).ToList();

        }
        if (!string.IsNullOrEmpty(firstDate) && !string.IsNullOrEmpty(lastDate))
        {
            DateTime dtfirstDate = Convert.ToDateTime(firstDate);
            DateTime dtlastDate = Convert.ToDateTime(lastDate);
            return (from r in db.requests
                       where r.reqDate <= dtlastDate && r.reqDate >= dtfirstDate 
                       select new ProductReqNoDate
                       {
                           departmant= r.departmant,
                           reqNo = r.reqNo ,
                           reqDate = r.reqDate,
                           prdctName= stringCutter((from p in db.products where p.reqNo == r.reqNo select p.prdctName).FirstOrDefault())
                       }).ToList();

        }
    }

回答1:

You can have the core of your query as the following:

var query = from r in db.requests 
select new ProductReqNoDate
                   {
                       departmant= r.departmant,
                       reqNo = r.reqNo ,
                       reqDate = r.reqDate ,
                       prdctName= stringCutter((from p in db.products 
                      where p.reqNo == r.reqNo select p.prdctName).FirstOrDefault())
                   }

Then apply if then else:

if (!string.IsNullOrEmpty(departmant))
    return  query.Where(r=>r.departmant== departmant).ToList();
if (!string.IsNullOrEmpty(firstDate) && !string.IsNullOrEmpty(lastDate))
{
        DateTime dtfirstDate = Convert.ToDateTime(firstDate);
        DateTime dtlastDate = Convert.ToDateTime(lastDate);
        return query.Where(r=> r.reqDate <= dtlastDate && r.reqDate >= dtfirstDate)
                    .ToList();
 }

It doesn't reduce if then else but makes more sensible, what going happens.



回答2:

1*

you can found better sollution but I wish this help (I thing) but I use it : you can make the test out this function

   List<ProductReqNoDate> yourList = GetRequestsQuery(string departmant, int reqStateID)

    if (!string.IsNullOrEmpty(firstDate) && !string.IsNullOrEmpty(lastDate))
    {
      yourdatagrid.Itemsource = yourList.where(a=> a.reqDate <= Datetime.parse(firstDate) & a.reqDate >= Datetime.parse(lastDate))
    }


public List<ProductReqNoDate> GetRequestsQuery(string departmant, int reqStateID)
{
    var db = new requestsDBEntities();
    var listPrn = new List<ProductReqNoDate>();
    if (!string.IsNullOrEmpty(departmant))
    {
        return  (from r in db.requests
                   where r.departmant== departmant
                   select new ProductReqNoDate
                   {
                       departmant= r.departmant,
                       reqNo = r.reqNo ,
                       reqDate = r.reqDate ,
                       prdctName= stringCutter((from p in db.products where p.reqNo == r.reqNo select p.prdctName).FirstOrDefault())
                   }).ToList();

    }
}

and you can apply any condition in your first list but in not recommended in havy application or many information in database.

2*

Or you can just make the first date and the last date; for exemple if the date is not set,make the first date = 01/01/1900 and the last date Datetime.Today and always pass your date in the linq query



回答3:

something like this I haven't compiled and checked it but it should give you a clue.

public List<ProductReqNoDate> GetRequestsQuery(string departmant, int reqStateID, string firstDate, string lastDate)
 {
    using(var db = new requestsDBEntities())
    {

      DateTime dtfirstDate =null;
      DateTime.TryParse(firstDate,out dtfirstDate);

      DateTime dtlastDate = null;
      DateTime.TryParse(lastDate,out dtlastDate);

      var result = (from r in db.requests
                   where 
                      (r.departmant == departmant)
                   || (r.reqDate <= dtlastDate.Value && r.reqDate >= dtfirstDate.Value)
                   select new ProductReqNoDate
                   {
                       departmant = r.departmant,
                       reqNo = r.reqNo ,
                       reqDate = r.reqDate ,
                       prdctName= stringCutter((from p in db.products where p.reqNo == r.reqNo select p.prdctName).FirstOrDefault())
                   }).ToList();
    }

 }

EDIT:

if you want to use non-sql functions in your filter then call ToList() on your table

 var result = db.requests.ToList().Where(r => { 

     // do test for what you want
     // so write a function to work out when you want to filter by
     // name or date
     return true;

 }).Select( r => new ProductReqNoDate
                   {
                       departmant = r.departmant,
                       reqNo = r.reqNo ,
                       reqDate = r.reqDate ,
                       prdctName= stringCutter(db.products.Where(p=> p.reqNo == r.reqNo).Select(p=> p.prdctName).FirstOrDefault())
                   })

the problem with this is that you are loading the whole table into memory which if fine if you don't change to values in it often and if it's not too big.

Another approach would be to write it as a stored proc which would probably make your DBA happy.