Home > Enterprise >  linq order by based on multiple columns and various crietria
linq order by based on multiple columns and various crietria

Time:09-17

I have data arranged in this order in sql.

enter image description here

Now, I want to order this list with both QuestionDataTypeId and DisplayOrder, but want this QuestionDataTypeId = 0 at last. so finally result will be like first row = 6 then 7 then 8 and then 1 to 5.

I want to achieve this with C# and linq.

What I have tried so far?

here is my code but it's not working.

var data = entity
    .OrderByDescending(m => m.QuestionDataTypeId == 0)
    .ThenBy(m => m.QuestionDataTypeId)
    .ThenBy(m => m.DisplayOrder);

I have fixed this with merging 2 different variables sorted separately for QuestionDataTypeId = 0 and all other QuestionDataTypeId, but just want to know what will be the proper linq for this case in single line.

any help would be really appreciated. thanks!

CodePudding user response:

You can write your own comparer for OrderBy

Sample data structure:

public record Table
{
    public Table(int qdtId, int displayOrder, string text)
    {
        QuestionDataTypeId = qdtId;
        DisplayOrder = displayOrder;
        Text = text;
    }

    public int QuestionDataTypeId {  get; set; }
    public int DisplayOrder {  get; set; }
    public string Text { get; set; }
}

public class TableComparer : IComparer<Table>
{
    public int Compare(Table? x, Table? y)
    {
        if(x.QuestionDataTypeId!= 0 && y.QuestionDataTypeId!=0 || x.QuestionDataTypeId == 0 && y.QuestionDataTypeId == 0)
        {
            return y.QuestionDataTypeId.CompareTo(x.QuestionDataTypeId);
        }
        return x.QuestionDataTypeId == 0 && y.QuestionDataTypeId != 0 ? int.MinValue : int.MaxValue;
    }
}

Then in the code:

List<StringConcatBug.Table> list = new()
{
    new(0, 1, "Comfortable"),
    new(0, 2,"attainable"),
    new(0, 3,"recent goal"),
    new(0, 4,"comfortable"),
    new(2, 2,"Last Name"),
    new(3, 3,"Email"),
    new(0, 5, "feeling"),
    new(1, 1, "First Name"),

};

var ordered = list.OrderByDescending(t=>t,new TableComparer());

foreach(var v in ordered) {  Console.WriteLine(v);}

Output

Table { QuestionDataTypeId = 1, DisplayOrder = 1, Text = First Name }
Table { QuestionDataTypeId = 2, DisplayOrder = 2, Text = Last Name }
Table { QuestionDataTypeId = 3, DisplayOrder = 3, Text = Email }
Table { QuestionDataTypeId = 0, DisplayOrder = 1, Text = Comfortable }
Table { QuestionDataTypeId = 0, DisplayOrder = 2, Text = attainable }
Table { QuestionDataTypeId = 0, DisplayOrder = 3, Text = recent goal }
Table { QuestionDataTypeId = 0, DisplayOrder = 4, Text = comfortable }
Table { QuestionDataTypeId = 0, DisplayOrder = 5, Text = feeling }

CodePudding user response:

I usually use this algorithm


var mult=100000; // You can select a different number depending how many records of 
                 //  the same type  you expecting; Numbers should not overlap

var data = entity
    .OrderBy(m => (m.QuestionDataTypeId*mult   m.DisplayOrder))
    .....

CodePudding user response:

Try replace QuestionDataTypeId where value = 0

.OrderBy(x=>x.QuestionDataTypeId==0?int.MaxValue:x.QuestionDataTypeId)
.ThenBy(t=>t.DisplayOrder)
  • Related