Mohsen
Mohsen

Reputation: 1108

Linq Dynamic OrderBy

I read other post and comments in StackOverflow.com but couldn't understand the solution.

Here is the code:

var qry = (from m in db.Messages
                           join r in db.Recievers on m.Id equals r.Message_Id
                           let a = m.SendDate
                           let b = (m.DoneDate != null ? m.DoneDate : DateTime.MinValue)
                           let c = m.Comments.Max(c => c.CommentDate)
                           let d = (c != null ? c : DateTime.MinValue)
                           let e = (radDropDownList1.SelectedIndex == 0 ? a : a >= b ? a >= d ? a : d : b >= d ? b : d)
                           orderby e descending
                           select m).Distinct();

Notes:

radDropDownList1 has two items. the 0 means the orderby must be based on SendDate of messages and 1 means the orderby must be based on the biggest value among SendDate, DoneDate and maximum date in comments. The above code does not return the result I expect. Please help me.

Upvotes: 0

Views: 123

Answers (2)

mihai
mihai

Reputation: 2804

The above code does not return the result I expect: you conditional expression is the cause

I would suggest you to write in this way:

let e = radDropDownList1.SelectedIndex == 0 ? a /*order by SendDate*/
                                                /*otherwise , order by MAX(a, b, c)*/
                                            : new DateTime(Math.Max(a.Ticks, Math.Max(b.Ticks, c.Ticks)))

EDIT:
Yes, sorry, as you mentioned, the SQL will not know about DateTime Ticks

Let's find the max in this way:

    var selectedIndex = radDropDownList1.SelectedIndex;

    var query =
        (from m in db.Messages
         join r in db.Recievers
           on m.Id equals r.Message_Id
         let a = m.SendDate

         let b = (m.DoneDate != null ? m.DoneDate : DateTime.MinValue)
         let c = m.Comments.Max(c => c.CommentDate)
         let d = (c != null ? c : DateTime.MinValue)

         let tempMax1 = a > b ? a : b
         let tempMax2 = tempMax1 > c ? tempMax1 : c

         let e = (
               selectedIndex == 0 ? a /*order by SendDate*/
                                  : tempMax2) /*otherwise , order by MAX(a, b, c)*/
         orderby e descending

         select m)
        .Distinct();

P.S. The elegance will be up to you ;)

Upvotes: 0

Maciej Los
Maciej Los

Reputation: 8591

As per my first look, the code to initiate e variable is wrongly written.

A proper if ... then ... elseif statement using conditional ?: operator should look like:

var answer = condition ? first_expression : second_expression

See: ?: Operator (C# Reference)

Let split it into multiple lines using standard notation:

if (radDropDownList1.SelectedIndex == 0)
  a
else if (a >= b)
  if (a >= d) 
   a
  else
    d
else if (b >= d)
  b
else
  d

Note: i do not use {} brackets to leave code more readible.

In case when you use multiple if... then ... elseif statements, you have to excercise special caution!

Upvotes: 1

Related Questions