views:

360

answers:

3

I have a linq-to-sql query over entity that has child entityset that I need to sort on some child fields, i.e. use this query:

   var query = from p in context.Patients 
            let order = p.Lab_Orders.First() 
            orderby order.Order_Date 
            select p; 

This query runs fine, but how would I modify it to use DLINQ OrderBy method what would I pass as a sorting parameter in run-time?

+1  A: 

If by DLINQ you mean Dynamic Query, then you can't use the query expressions like that, you have to use extension methods with lambdas. You can start with a query expression but you have to eventually switch it over to lambda:

IEnumerable<Patient> GetPatients(string orderSortField)
{
    var query =
        from p in context.Patients
        select new
        {
            Patient = p,
            FirstOrder = p.Lab_Orders.First()
        };
    return p.OrderBy(orderSortField).Select(p => p.Patient);
}

Call it with:

var patientsByOrderDate = GetPatients("FirstOrder.Order_Date");
Aaronaught
Thanks for the reply. That is exactly what I meant - Dynamic LINQ. Ssory about the confusion, somehow I was thinking everyone knows what it is since we use this terminology at my workplace:-) Just one question - sometimes we have new patients with NO associated lab orders yet. Obviously in this case I don't care about such sorting. Should I just replace First() with FirstOrDefault()?
Victor
@Victor: If you replace with `FirstOrDefault` and try to sort on `FirstOrder.Order_Date`, you'll get a `NullReferenceException` if any records don't have orders. If it's possible for there to be no orders, I'd suggest breaking out the order date explicitly, as in: `FirstOrderDate = p.Lab_Orders.FirstOrDefault(o => (DateTime?)o.Order_Date)`, then sort on `FirstOrderDate`.
Aaronaught
It is possible that there will be no orders but new patients processed separately, i.e. either all Patients have orders, or they all don't. But, I think your advice stands, so I will do that.
Victor
A: 

Try to add the "OrderBy" to the expression tree:

var query = from p in context.Patients 
            let order = p.Lab_Orders.First() 
            select p; 
var x = Expression.Parameter(query.ElementType, "x");
string sortName = "order.Order_Date";
var selector = Expression.Lambda(Expression.PropertyOrField(x, sortName), x);
query = query.Provider.CreateQuery(
         Expression.Call(typeof(Queryable), "OrderBy", 
              new Type[] { query.ElementType, selector.Body.Type },
               query.Expression, selector)
         ) as IQueryable<Patients>;

Needs the namespace "System.Linq.Expressions".

Stephan Keller
Thanks for reply. While I like to create and use expressions don't think one needed here since dynamic linq creates one for you anyways.
Victor
A: 

Use the AsQueryable() after the initial statement -

var query = from p in context.Patients
            let order = p.Lab_Orders.First()        
            select p; 

query = query.AsQueryable().OrderBy(x => x.Lab_Orders.First().OrderDate);
RobS
Thanks for reply. Need to use Dynamic LINQ
Victor