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)
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?
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