views:

64

answers:

3

Hi guys,

I'm trying to build a query using linq-to-sql and, in order to provide sorting capabilities, I wrote something like this:

private Dictionary<string, Expression<Func<DataAccess.Auditing, object>>> OrderDict { get; set; }


OrderDict = new Dictionary<string,Expression<Func<Augeos.GereonWeb.DataAccess.Auditing, object>>>();
OrderDict.Add("Date", p => (DateTime)p.RequestDateTime);
OrderDict.Add("Username", p => (string)p.CdUsername);
OrderDict.Add("Portfolio", p => (string)p.CdPortfolio);
OrderDict.Add("Url", p => (string)p.RequestedUrl);
OrderDict.Add("Result", p => (bool)p.RequestResult);
OrderDict.Add("Duration", p => (float)p.RequestDuration);


private IQueryable<DataAccess.Auditing> SetOrder(string orderBy, bool orderDirection, IQueryable<DataAccess.Auditing> query)
{
    if (orderDirection)
    return query.OrderByDescending(OrderDict[orderBy]);
    else
    return query.OrderBy(OrderDict[orderBy]);
}

My goal is to use the SortOrder function to sort the query. The main problem is that Func returns an object and linq cannot sort elements of this type. I truly need to use object as a return type because I have to sort by a wide range of types. Is it actually possible to slightly modify this code and make it to work?

Thank you,

Gio

+2  A: 

Hm you'd have to go very low-level in the expression tree of your query to do such a thing. A much easier way would be to use the DynamicLinq library, where you can do .OrderBy() with a column as string value. Documentation can be found here on Scott Guthrie's blog.

Joachim VR
A: 

If you imagine ordering your query like so:

query = orderDict["Date"](query, true);

Then your dictionary would have to be defined like this:

var orderDict = new Dictionary<string, Func<IQueryable<Auditing>, bool, IQueryable<Auditing>>>();

and you could add items to it like so:

orderDict.Add("Date", MakeOrderedQueryDelegate(a => a.RequestDateTime));
orderDict.Add("UserName", MakeOrderedQueryDelegate(a => a.CdUsername));

which would need a MakeOrderedQueryDelegate to be like this:

private Func<IQueryable<Auditing>, bool, IQueryable<Auditing>> MakeOrderedQueryDelegate<T>(Expression<Func<Auditing, T>> keyselector)
{
    return (q, descending) => { return MakeOrderedQuery(q, descending, keyselector); };
}

..and you can implement MakeOrderedQuery like this:

private IQueryable<Auditing> MakeOrderedQuery<T>(IQueryable<Auditing> query, bool descending, 
    Expression<Func<Auditing, T>> keyselector)
{
    if (descending)
    {
        return query.OrderByDescending(keyselector);
    }
    else
    {
        return query.OrderBy(keyselector);
    }
}
Leon van der Walt
A: 

To build a dynamic query, see my answer to this question.

Danny Chen