A better way to filter on projections

Posts   
 
    
mihies avatar
mihies
User
Posts: 800
Joined: 29-Jan-2006
# Posted on: 06-Feb-2009 13:29:37   

Here is my query that caused problems (and now runs fine thanks to fix)

(from ld in meta.Location
                            select new
                            {
                                Id = ld.Id,
                                Title = ld.Name,
                                Events = from e in ld.EventName
                                         where  (from g in e.Game select g).Count() > 0
                                         select new
                                         {
                                             Id = e.Id,
                                             Title = e.Name,
                                             Count = (from g in e.Game select g).Count()
                                         }
                            }

I have to repeat same Count clause twice. Thus I tried grouping (northind example) to avoid typing same clause twice (I would where on group):

var query = from c in meta.Categories
                        group c by c.CategoryId into g
                        select new { g.Key, Cnt = g.Sum(x => x.Products.Count()) };

Perhaps I am doing something but I get this error when I introduce Cnt property:

An item with the same key has already been added.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 06-Feb-2009 15:56:01   

(not tested) from ld in meta.Location select new { Id = ld.Id, Title = ld.Name, Events = from e in ld.EventName let cnt = (from g in e.Game select g).Count() where cnt > 0 select new { Id = e.Id, Title = e.Name, Count = cnt } }

but it could go wrong, as 'let' is a complex system. (edit) I see this goes wrong as it misses the correlation filter between the nested queries. This is a bit of a complex situation as the 'let' burries the correlation filter (e.Game) into a different query. So forget 'let' in subqueries. If you're worrying about the count executed twice, you can use any though I ran into a glitch there.

AAAARGG rage Linq is the most frustrating piece of (#*$($@ I've ever worked with. You can't create solid code for it, as everything is connected to eachother, changing this invalidates that etc.

I reproduced the group by issue rage What's weird is that I have many tests similar to this one which pass...

I've no idea what causes this but I saw where it occurs, stay tuned, for bugfix 328975239423 on the linq provider. disappointed

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 06-Feb-2009 16:27:37   

Ok! simple_smile (getting mad on code always helps to find an answer quickly wink )

Attached, new dll with fixes for: - Any/All without lambda - your groupby issue. It was caused by helped code which did its best to make very complex group by queries work, but forgot in the process to check whether fields were already in the projection.

Your initial query can now be:

from ld in meta.Location
                            select new
                            {
                                Id = ld.Id,
                                Title = ld.Name,
                                Events = from e in ld.EventName
                                         where e.Game.Any()
                                         select new
                                         {
                                             Id = e.Id,
                                             Title = e.Name,
                                             Count = e.Game.Count()
                                         }
                            }

Frans Bouma | Lead developer LLBLGen Pro
mihies avatar
mihies
User
Posts: 800
Joined: 29-Jan-2006
# Posted on: 06-Feb-2009 17:56:43   

Hi Frans,

Thanks for working on fixes. I feel your pain btw. The reasoning behind group query was that where condition can get prety complex and writting same code twice is not the best practice :-) Funny, my first though was let statement as well and of course it didn't work. I've came to pretty much the same conclusion about the let - it has to be complex beast.