Dynamic Linq

Dynamic Linq

Old forum URL: forums.lhotka.net/forums/t/8626.aspx


FrazerS posted on Sunday, March 07, 2010

If I provide a reference to System.Linq.Dynamic (assembly obtained from CSharpSamples) in my UI, the following works:

 employees = Business.EmployeeList.GetEmployeeList():
bsEmployees.DataSource = employees.OrderBy("LastName").Skip(4).Take(3);

(where EmployeeList is an ERL and bsEmployees a Windows.Forms.BindingSource)

But, figuring that its not such a good idea to do the sorting and paging on the client, I try to move this to the factory method in the ERL:

public static EmployeeList GetEmployeeList(string sortProperty, int startItem, int pageSize)
{
    return (EmployeeList)DataPortal.Fetch<EmployeeList>().OrderBy(sortProperty).Skip(startItem).Take(pageSize);
}

This builds okay, but throws on execution with:

Unable to cast object of type 'System.Linq.EnumerableQuery`1[Business.Employee]' to type 'Business.EmployeeList'

Why does this work in the client but not in the business object?

Frazer

RockfordLhotka replied on Sunday, March 07, 2010

LINQ can have some unexpected and unintended side-effects. You need to understand how it works or you can get into trouble.

LINQ queries create a completely new list object as a result. This list object is not connected to the original list, and is not of the same type (normally it is just an IEnumerable<T>, which is the most basic list type in .NET).

What's confusing is that the elements in the list are the same elements from the original list - so you can interact with them and it works fine. But if you add or remove items from the query result they won't be added/removed from the original list - and in a CSLA setting this means they won't be persisted.

This is the reason for LinqBindingList - see Chapter 14 (I think) for details about the problem and solution.

In CSLA 4 the new LinqObservableCollection solves the problem too - but in a different way.

In the end though, returning the result of the query from your factory method is problematic. The reason is that the UI would then have a reference to something that isn't the original list - so things like saving the object won't work - you won't even have a Save() or BeginSave() method to call.

Copyright (c) Marimer LLC