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?


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