V2.6 and Linq to Objects

Posts   
 
    
arschr
User
Posts: 894
Joined: 14-Dec-2003
# Posted on: 29-Feb-2008 18:04:29   

Frans, Based on your blog posts and a few messages here, I believe, v2.6 will center around providing a Sql to LlblGen Entity/EntityCollection layer that uses Linq syntax to fill and save from the database.

For me, the Linq to Objects, (or in memory manipulation of Entity Collections and Entity Views) is the interesting area. Today, to use linq with LlblGen, I am using the Cast or TypeOf extension methods since the collections I use don't support IEnumerabl<T>.

Will this interface be supported in v2.6?

Would you discuss what we should expect to see related to Linq to Objects?

Thanks.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39905
Joined: 17-Aug-2003
# Posted on: 29-Feb-2008 20:36:35   

The main focus is indeed on providing a querying methodology similar to our own query api for reading data from the db.

There are indeed other areas where Linq and thus linq to objects, can be used, for example with filters/sorters in entityviews and general usage of collections in linq queries.

The collections implement IEnumerable, not IEnumerable<T>. I haven't done any testing with linq to objects and entity collections yet, so you can't use the collection usefully, because type information is lost and you therefore have to cast all over the place?

I've added IEnumerable<T> to CollectionCore<T>, so all collections now implement it (in v2.6). If you're working with IEntityCollection(2) typed parameters, you can only use IEnumerable, which is logical, as there's no type argument in the interface.

The main challenge with adding code for linq to objects is to avoid needing a specific .NET 3.5 build library version. All linq stuff is now in a separate dll, so the ormsupportclasses are still .net 2.0 build (as .net 3.5 is the .net 2.0 CLR anyway), so it might be it will be more difficult to add linq-based filters to views but we'll see about that after the Linq to LLBLGen Pro ctp (hopefully next week, hierarchical fetches of dynamic lists (lists of anonymoustypes) is still not done) has been released what should be added as well. simple_smile

Frans Bouma | Lead developer LLBLGen Pro
arschr
User
Posts: 894
Joined: 14-Dec-2003
# Posted on: 29-Feb-2008 22:29:12   

The collections implement IEnumerable, not IEnumerable<T>. I haven't done any testing with linq to objects and entity collections yet, so you can't use the collection usefully, because type information is lost and you therefore have to cast all over the place?

My code looks like this


IEntityCollection2 _collection = fitc.PayLoad[typeof (InvoiceTracker01Entity)];
                
IEntityView2 work;
            
work = _collection.CreateView();
var result3 = from invoice in [b]work.Cast<InvoiceTracker01Entity>()[/b]
                    where (invoice.CurrentActivityId == 7)
                    group invoice by new { invoice.BaseFormat } into currentActivities
                    orderby currentActivities.Key.BaseFormat
                    select new
                    {
                       BaseFormat = currentActivities.Key.BaseFormat,
                       InBalanceInvoices = currentActivities.Sum(invoice =>                     invoice.IsInBalanceCount),
                                      OutOfBalanceInvoices = currentActivities.Sum(invoice => invoice.IsOutOfBalanceCount),
                                      UnknownBalanceInvoices = currentActivities.Sum(invoice => invoice.BalanceUnknownCount)
                                  };

                    gridControl1.DataSource = [b]result3.ToList()[/b];
                    aurgumentDataMember = "BaseFormat";


So the casting isn't too much but i'm concerned about the efficiency of work.Cast<InvoiceTracker01Entity>() and that it enumerates the view at that poin rather than waiting until the rustult3.ToList() line is run.

The main challenge with adding code for linq to objects is to avoid needing a specific .NET 3.5 build library version. All linq stuff is now in a separate dll, so the ormsupportclasses are still .net 2.0 build (as .net 3.5 is the .net 2.0 CLR anyway), so it might be it will be more difficult to add linq-based filters to views but we'll see about that after the Linq to LLBLGen Pro ctp

Could it be done with extension methods in a seperate dll, so the 3.5 stuff would reside there?

As an alternative, for my use anyway, aggregates on entity views would eliminate much of my need for Linq (at least right now). wink

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39905
Joined: 17-Aug-2003
# Posted on: 01-Mar-2008 11:46:43   

arschr wrote:

The collections implement IEnumerable, not IEnumerable<T>. I haven't done any testing with linq to objects and entity collections yet, so you can't use the collection usefully, because type information is lost and you therefore have to cast all over the place?

My code looks like this


IEntityCollection2 _collection = fitc.PayLoad[typeof (InvoiceTracker01Entity)];
                
IEntityView2 work;
            
work = _collection.CreateView();
var result3 = from invoice in [b]work.Cast<InvoiceTracker01Entity>()[/b]
                    where (invoice.CurrentActivityId == 7)
                    group invoice by new { invoice.BaseFormat } into currentActivities
                    orderby currentActivities.Key.BaseFormat
                    select new
                    {
                       BaseFormat = currentActivities.Key.BaseFormat,
                       InBalanceInvoices = currentActivities.Sum(invoice =>                     invoice.IsInBalanceCount),
                                      OutOfBalanceInvoices = currentActivities.Sum(invoice => invoice.IsOutOfBalanceCount),
                                      UnknownBalanceInvoices = currentActivities.Sum(invoice => invoice.BalanceUnknownCount)
                                  };

                    gridControl1.DataSource = [b]result3.ToList()[/b];
                    aurgumentDataMember = "BaseFormat";


So the casting isn't too much but i'm concerned about the efficiency of work.Cast<InvoiceTracker01Entity>() and that it enumerates the view at that poin rather than waiting until the rustult3.ToList() line is run.

If you used EntityCollection<InvoiceTracker01Entity> instead of IEntityCollection2 and used that as the source of your query, it might work with v2.6. With the untyped IEntityCollection2 interface, you don't have a type specification, so I doubt it will work without the cast. Linq to objects isn't the fastest btw, MS is currently busy optimizing the linq to objects code, but don't be surprised that our own predicates are faster in-memory.

The main challenge with adding code for linq to objects is to avoid needing a specific .NET 3.5 build library version. All linq stuff is now in a separate dll, so the ormsupportclasses are still .net 2.0 build (as .net 3.5 is the .net 2.0 CLR anyway), so it might be it will be more difficult to add linq-based filters to views but we'll see about that after the Linq to LLBLGen Pro ctp

Could it be done with extension methods in a seperate dll, so the 3.5 stuff would reside there?

As an alternative, for my use anyway, aggregates on entity views would eliminate much of my need for Linq (at least right now). wink

Aggregates on views in our own framework won't happen, it's really complex to do and actually redundant with linq to objects available. Also, views are for viewing entities, so aggregates show rows of data in new tuples, not entities.

Extension methods aren't going to work here I think, or we might be talking about different things simple_smile What I meant was teh filters and sorters specified to create a view on a collection. You now specify a predicateexpression and a sortexpression. What should be possible is produce a view on a collection produced by a linq query on the collection, so the result of the linq query on the collection is the view.

A linq to objects query is really just a delegate (Func<T, ...>), the challenge is to call it efficiently, thus with a known signature so code internally can do Invoke(param1, ..) instead of DynamicInvoke(...) which is dogslow.

This is also how I managed to add delegates build with lambdas to projectors in .NET 2.0 code simple_smile

So looking at your code, I don't think you need the view. With IEnumerable<T> implemented on the collection, you could get rid of the cast and you don't need the view (you don't need it today as well, am I right?). With 2.6, you'll be able to perform this same query on the db as well.

Frans Bouma | Lead developer LLBLGen Pro
arschr
User
Posts: 894
Joined: 14-Dec-2003
# Posted on: 01-Mar-2008 13:17:49   

So looking at your code, I don't think you need the view. With IEnumerable<T> implemented on the collection, you could get rid of the cast and you don't need the view (you don't need it today as well, am I right?). With 2.6, you'll be able to perform this same query on the db as well.

Two points: 1) I don't need the view for this, but, I've build other code to work off of views. 2) Hitting the database again for these summarizations of information I already would be bad for a number of reasons. Performance and the summary matching the detail being two that I can think of right off.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39905
Joined: 17-Aug-2003
# Posted on: 01-Mar-2008 13:46:50   

arschr wrote:

So looking at your code, I don't think you need the view. With IEnumerable<T> implemented on the collection, you could get rid of the cast and you don't need the view (you don't need it today as well, am I right?). With 2.6, you'll be able to perform this same query on the db as well.

Two points: 1) I don't need the view for this, but, I've build other code to work off of views.

Sure, and it should work with views AND entitycollections. I think the main issue is that if the type is IEntityView2, or IEntityCollection2, the compiler will require you to specify a cast as it can't determine what the real type is of the entity in the view or collection. So in these cases, if you want to avoid the cast, you should use EntityView<T> and EntityCollection<T>. This is something which can't be changed, as it would otherwise require a generic argument in IEntityCollection(2) which is making the whole interface void, as the interface is usable for accessing the collection without knowing the type of T wink

2) Hitting the database again for these summarizations of information I already would be bad for a number of reasons. Performance and the summary matching the detail being two that I can think of right off.

If you need to access the db again, then indeed it's expensive. If you don't need the set of entities for other purposes than this, it might be a better choice to do it in the db. The reason is that db's are optimized for this kind of work, and doing it in-memory using imperative loops can be slower (added to that that you've to transport the data outside the db.). So it's not a given that things are always faster in the db or always faster in the client, it depends on the situation.

Frans Bouma | Lead developer LLBLGen Pro
arschr
User
Posts: 894
Joined: 14-Dec-2003
# Posted on: 01-Mar-2008 13:52:34   

So it's not a given that things are always faster in the db or always faster in the client, it depends on the situation.

Do you mean to say that there are things in life that aren't black or white? What a strange idea! sunglasses

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39905
Joined: 17-Aug-2003
# Posted on: 01-Mar-2008 15:40:38   

arschr wrote:

So it's not a given that things are always faster in the db or always faster in the client, it depends on the situation.

Do you mean to say that there are things in life that aren't black or white? What a strange idea! sunglasses

I hate to admit it, but in RARE edge cases, it indeed might be (I'm told) wink

Frans Bouma | Lead developer LLBLGen Pro