LINQ to CSLA (Chapter 14)

LINQ to CSLA (Chapter 14)

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


rxelizondo posted on Wednesday, October 28, 2009

Hello

I am hoping to hit chapter 14 of the book pretty soon (this weekend if all goes well). The chapter is titled LINQ to CSLA.

Before I read the chapter and spend time dinging into it, I would like to know if someone could tell if the chapter still relevant or not.

The reason why I ask is because on one post Rocky wrote “And I think the LINQ to CSLA implementation (at least LinqBindingList) was a mistake”. I realize that he was being specific about the LinqBindingList implementation but I kind of got the feeling (reading between the lines) that he may not be too happy about the whole LINQ to CSLA implementation.

I am sure that digging into LINQ to CSLA would be a good learning experience no matter what, but right now, I rather spend the time digging into other parts of the framework that may be more beneficial to me at this point…… I thought that catching up from CSLA 2.x to 3.x was going to be a breeze but I was wrong!!

Thank you.

RockfordLhotka replied on Wednesday, October 28, 2009

Chapter 14 is mostly about how L2C was implemented. So if you want to learn how to create a custom query provider and do some other very advanced LINQ stuff it should be interesting.

If you want to learn how to use L2C, there's really not a lot to it. There are only a couple features:

  1. Indexed queries
  2. LinqBindingList as a result of identity projection queries against a BusinessListBase

Indexed queries are useful if you have a collection that you keep in memory over a period of time, and against which you do many queries. If this isn't your scenario then the cost of building the index will outweigh any benefit. But if this is your scenario, once the index is built the queries will usually run ~10,000 times faster (really).

The bigger feature is LinqBindingList (LBL). This is necessary (and explained in Chapter 14) because LINQ to Objects returns an IEnumerable<T> as the result of a query, and that is the most basic featureless collection type in .NET. So it doesn't support data binding in Windows Forms or WPF (not fully anyway). And worse, if you add or remove an item from that list, it has no effect on the real list, which can be confusing.

So doing this:

var data = from r in myList where r.Id > 123 select r;

will return an LBL if myList is a BLB. The LBL is fully bindable, and is a view over the original list, so if you add or remove items from the result of the query, they are added/removed in the original list too.

I said this was a mistake, because this required creating a custom query provider so the query returns the LBL. Implementing a custom query provider is incredibly non-trivial (fancy talk for "really f*cking hard"), and it has turned out to be a maintenance pain point.

Additionally, as I look at version 4.0 where I'll need to have support for ObservableCollection and BindingList this gets really complex, because the query provider will need to generate an LBL or LOC (LinqObservableCollection) - increasing the complexity further.

I think (and Aaron agrees) that a better solution is to have extension methods like ToLinqBindingList() and ToLinqObservableCollection():

var data = (from r in myList where r.Id > 123 select r).ToLinqBindingList();

The result would be the same - an LBL providing a bindable view over the original list - but the complexity would be radically reduced because there's no need for a custom query provider.

AaronErickson replied on Wednesday, October 28, 2009

Note - we would still be doing a custom query provider - but it would work in a manner similar to how PLinq works with .NET 4, i.e. ToParallel() invokes the QP that has the Parallel operations on any IE, overriding the default QP.

So there is still a custom QP, it just becomes more optional, which should help make linq code with csla work more predictably.

As indexing can work without having to use a special QP, I think indexing probably stays in the default impl.  Though one change we could consider is implementing the query spec stuff we did in i4o over here as well.  That is, in addition to specification of indexing via attributes, you can specify them via lambdas as well - allowing for changes and optimizations to indexing at runtime.

All open to discussion...

Jack replied on Wednesday, October 28, 2009

An optimized parallel processing and then optional bindable linq query in Silverlight would be the killer feature for me.  I have found that I am using LINQ everywhere in my application but not being able to bind to the query really sucks.

I've had to do a lot more binding to the unfiltered BO collection and then doing all the filtering logic on the UI side in my ViewModel.  Not terrible but it changes the whole dynamic of the application. 

Of course I would benefit from indexes then as well.

I really like the extensions as well - means it will be simple for me to re-work what I have done.

Jack

RockfordLhotka replied on Wednesday, October 28, 2009

Aaron, would it make sense to pull indexing out of CSLA, and people who want that feature can use use i4o? Or is i4o incompatible with CSLA objects?

AaronErickson replied on Friday, October 30, 2009

i4o still depends on inheritance, as it needs a place to store the indexes.  The alternative would be to create a structure that creates an external index that listens to the change events of the collection in order to manage adds/removes/changes, but that is far away from what i4o does.  So I don't think that will work.

As of now, the indexing query handling is done through extension methods. but the indexes themselves have to be in the collection.

garybr replied on Wednesday, September 01, 2010

I know this is an old thread, but from looking at the latest i4o it appears to still depend on inheritance. So, if I want to use with CSLA collections, even with my own base classes, it looks like I'll need to implement the creation and management of the indexes.

RockfordLhotka replied on Wednesday, September 01, 2010

That may be true, I haven't kept up with i4o. I suspect Aaron maybe has lost interest in it? I know he's no longer active with CSLA.

I do know that the complexity (on a couple levels) involved in having indexing built into BLB/ROLB was higher than I was willing to deal with for CSLA itself. Indexed collections are an edge case - important if you need them, but most people don't. And it just wasn't worth the ongoing pain necessary to support that edge case.

garybr replied on Wednesday, September 01, 2010

I agree, it's a rare case. I also see interfaces in i4o which look like they would allow for custom collections (CSLA and derivatives) to leverage the extension methods. I'm looking at using for some isolated cases where cached collections need to be filtered by some arbitrary lambda. When the collection grows, the query can definitely use an index and since the source is cached the index would be reused multiple times.

Copyright (c) Marimer LLC