简体   繁体   中英

linq conditional query

What would be the best practice for setting a status depending on several other "columns" retrieved in a linq query.

  var result = (from q in query
                select new Item
                         {
                           ApprovedDate = q.ApprovedDate,
                           CreatedDate = q.CreatedDate,
                           DeclinedDate = q.DeclinedDate,
                           Status = 0
                         });

I'd like to set the status to either 0, 1, 2.

(ApprovedDate == null and DeclinedDate == null) --> 0
(ApprovedDate != null and DeclinedDate == null) --> 1
(DeclinedDate != null) --> 3

So perhaps something like:

  var result = (from q in query
                select new Item
                         {
                           ApprovedDate = q.ApprovedDate,
                           CreatedDate = q.CreatedDate,
                           DeclinedDate = q.DeclinedDate,
                           Status = (q.CreatedDate == null && q.DeclinedDate == null) ? 0 : (q.ApprovedDate != null && q.DeclinedDate == null) ? 1 : 2
                         });

I might add even more status combinations, so should I try and do this in the linq select query, in my repository object.. Or later on in the controller where I would do a .ToList() and then foreach the list to set the correct status code?

Having even more than 3 statuscodes, the linq query gets "hard" to read.

What about moving status calculation to Item class? If status property depends on other properties value, then it's definitely calculated property:

var result = from q in query
             select new Item
                         {
                           ApprovedDate = q.ApprovedDate,
                           CreatedDate = q.CreatedDate,
                           DeclinedDate = q.DeclinedDate
                         });

And

public class Item
{
  // other properties

  public int Status
  {
      get
      {
          if (ApprovedDate == null and DeclinedDate == null)
              return 0;
          if (ApprovedDate != null and DeclinedDate == null)
              return 1;
          if (DeclinedDate != null)
              return 3;
          // etc
      }
  }
}

Actually I think it's best option, because in this case status calculation logic will be close to required data. If (for some reason) you can't use this approach, then move setting statuses to local items collection:

var items = result.ToList().ForEach(i => i.Status = CalculateStatus(i));

Maybe wrapped all in a function An do a linq like this

var result = (from q in query sele q).AsEnumerable()
                                       .Select( x => new Item()
                                       {
                                           ApprovedDate = x.ApprovedDate,
                                           CreatedDate = x.CreatedDate,
                                           DeclinedDate = x.DeclinedDate,
                                           Status = MyStatusFunction(x.CreatedDate,q.DeclinedDate)
                                       });


public int MyStatusFunction(DateTime ApprovedDate , Datetime DeclinedDate)
{
    if (ApprovedDate == null and DeclinedDate == null) return 0;
    else if(ApprovedDate != null and DeclinedDate == null) return 1;
    else if (DeclinedDate != null) return 3;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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