0

I have a list that comes from a database and want to sort the DateofCreation variable from that list. It's datatype is in string.

How do I go about it?

I went about doing what was instructed in this site here

and revised it to fit my code, the error is

Error CS0834 A lambda expression with a statement body cannot be converted to an expression tree

var orderedList3 = collectionRecords.OrderByDescending(x =>
{
      DateTime dt;
      if (!DateTime.TryParse(x.DateOfCreation, out dt)) return DateTime.MaxValue;
      return dt;
});

collectionRecords comes from

public class CollectionRecords
{
    [Key]
    ...
    ...
    public string AuthorSource { get; set; }
    public string DateOfCreation { get; set; }
    public string VolumeIssueNo { get; set; }
    ...
}

Sample Input:

  • undated
  • 1991 May 8
  • march 2012
  • various dates
  • Apr 8 2018

Expected Output:

  • Apr 8 2018
  • March 2012
  • 1991 May 8
  • various dates
  • undated
Michał Turczyn
  • 32,028
  • 14
  • 47
  • 69
  • What's your full code? Just the line with the lambda expression. I don't see anything wrong with the code you posted above. At least syntactically speaking. – Tyress May 14 '19 at 04:06
  • @Tyress I've updated the question, It wasn't shown because of a typo error – Nikki Munoz May 14 '19 at 04:13
  • 3
    How 1991 May 8 comes before March 2012 ? I think you need to updated your expected output – Venkataraman R May 14 '19 at 04:16
  • 1
    Possible duplicate of ["A lambda expression with a statement body cannot be converted to an expression tree"](https://stackoverflow.com/questions/5179341/a-lambda-expression-with-a-statement-body-cannot-be-converted-to-an-expression) – default locale May 14 '19 at 04:30
  • updated question @VenkataramanR – Nikki Munoz May 14 '19 at 06:18
  • @defaultlocale I tried the method, but it doesn't seem to work? `var orderedList3 = collectionRecords.OrderByDescending(x => { var y = x.DateOfCreation; DateTime dt; if (!DateTime.TryParse(y, out dt)) return DateTime.MaxValue; return dt; });` – Nikki Munoz May 14 '19 at 06:23
  • *March 2012* is not a valid date it needs a day number, how it should converted as a date? -HTH ;). – shA.t May 14 '19 at 06:25
  • "various dates" and "undated" is not also a date, that's why TryParse is called to try if it can be turned into a date, if not then it is put at the bottom @shA.t – Nikki Munoz May 14 '19 at 06:28
  • But for example, when you have *March 2012* and *2012 march 1* in your list how those should sorted as your expected result? – shA.t May 14 '19 at 06:31
  • 1
    @NikkiMunoz please, read the explanation first. You're still trying to use the complex code block instead of a simple expression. This will work for a [`List`](https://stackoverflow.com/questions/14667754/), but won't work for ling-to-sql collection. What you can do is to [convert `collectionRecords` to `List`](https://stackoverflow.com/questions/755826/) (`collectionsRecords.ToList().OrderByDescending(...`) and then sort it however you want, but this will potentially lead to suboptimal performance, as the list is going to be sorted on the client side. – default locale May 14 '19 at 06:35

3 Answers3

0

Firstly, you should not be using strings as dates, that is why you end up having to convert them to DateTime first before ordering. If you ever need to store a date store it as a date, not as a string.

Expected value is as well wrong as it seems. If I run your code through LinqPad I get a correct output of Apr 8 2018 march 2012 1991 May 8 various dates undated

but this requires DateTime.MinValue not Max value to be returned.

As well I get the same output in VS. What is the context of collectionRecords? It maybe IQuerable? I think if you try to convert it to an array or IEnumerable before ordering it should work like a charm.

UPDATED: How do you store it in the Database? as a string or as a date? Create a migration to the database and store it as a date, unless you are specifically required to store those as strings and store such values as "various dates" or "Undated", which is a bit wrong as you are breaking the concept of DateTime. You should not store anything else in a DateTime Database fields, or store DateTime type fields in a string/vrchar type columns. It is better to have two separate columns in Database, for example: Datetime type column which stores only the dates and have a boolean type column like "IsUdated".

Of course it all depends on the software you are working if you can make those changes, otherwise, you need to do what you are already doing, just make sure, the types you are using for expression are correct, not IQuerable, but a list or an IEnumerable.

vsarunov
  • 1,433
  • 14
  • 26
0

You could implement IComparable interface, and override method CompareTo, to decide the default sorting order.

ascripter
  • 5,665
  • 12
  • 45
  • 68
Amit Kumar
  • 360
  • 2
  • 10
0

You should probably listen to the other people commenting about the database structure, but to get around the expression tree error you can execute the statement on the DB first by:

var orderedList3 = collectionRecords.ToList().OrderByDescending(x =>
{
      DateTime dt;
      if (!DateTime.TryParse(x.DateOfCreation, out dt)) return DateTime.MaxValue;
      return dt;
});

Going forward not a good idea to have this at all especially if you have more data.

Tyress
  • 3,573
  • 2
  • 22
  • 45