Friday, March 6, 2009

C# Puzzle No.13 (advanced)

Using LinqToSQL is fun and speeds up a lot of things. However, there are issues with LinqToSQL which confuse people. Ultimately, some of these people tend to think that LinqToSQL is useless because things that should be obvious are not such obvious. Over a year ago I wrote a short blog entry on one of such basic issues.

Another such "not-so-obvious" thing is the issue of "ordering". One of the common requirements is to be able to order by the name of the property and not by the property itself. For example, if you use ObjectDataSource, then you know that the sorting parameter is passed to the object responsible for data retrieving by name of the parameter.

Let's take a look at two LinqToSQL ordering attempts:

   1: ConcreteDataContext ctx = new ConcreteDataContext();
   2:  
   3: /* this is easy */
   4: var list = from elem in ctx.TheTable
   5:            orderby elem.Property
   6:            select elem;
   7:  
   8: /* this will compile
   9:    however it does not work
  10: */
  11: string PropertyName = "Property";
  12: var list = from elem in ctx.TheTable
  13:            orderby PropertyName
  14:            select elem;

In the example code above, the first linq clause is obvious - the ordering uses the property "Property" in a direct way. However, in in the second clause we use the name of the property.


You are to answer two following questions:


1. Why the second clause does not produce correct results, although it compiles correctly?


2. How is it possible then to build generic linq expressions which sort objects by names of their properties.


By generic I mean that following solution is not acceptable:



   1: switch ( PropertyName )
   2: {
   3:    case "Property":
   4:  
   5:       return from elem in ctx.TheTable
   6:              orderby elem.Property
   7:              select elem;
   8:  
   9:    case "AnotherProperty":
  10:  
  11:       return from elem in ctx.TheTable
  12:              orderby elem.AnotherProperty
  13:              select elem;
  14:  
  15:    ...
  16:  
  17: }

2 comments:

Deto said...

1. Why the second clause does not produce correct results, although it compiles correctly?


Well, from the exact definition of the OrderBy() extension we see:

public static IOrderedEnumerable<TSource&gtOrderBy&ltTSource, TKey>(this IEnumerable<TSource>source, Func&ltTSource, TKey& keySelector);

soo if I type :

order by "string"

is preety much the same as:

.OrderBy(x => "string")

Which is:

.OrderBy<MyClass,string>(x => "string")


2. How is it possible then to build generic linq expressions which sort objects by names of their properties.

Dont know yet :)

Wiktor Zychla said...

hint: the general solution I think of is provided by Microsoft, although it is not a part of built-in Linq but rather it's provided as a separate download. it's not related however to the Entity Framework in any way and is fully usable in Linq to SQL.