Issue with Count() in LINQ Where condition

787 views
Skip to first unread message

mare

unread,
Dec 11, 2012, 1:52:05 PM12/11/12
to rav...@googlegroups.com
I'm having an issue with the following code:
 
      var imagelessProducts = _session.Query<Product>().Where(p=>p.Images.Count == 0).ToList();
where Images is of type Dictionary<string, Image>. The query always returns empty list. There are Products with empty Images collections in there. However, if I do Count > 0 it does return all Product docs, which is incorrect again. It seems like it only checks the existance of the Images collection but not the actual contents.
 
Also p=p.Images.Any() throws Index out of range exception.
 
?

Matt Johnson

unread,
Dec 11, 2012, 2:42:06 PM12/11/12
to ravendb
Congrats, you hit a true bug. :) I'll write it up.

It has to do with dictionaries. It would work fine if you were using
a list or array.

In the meantime, you can work around it with a static index.


public class Products_ByImageCount :
AbstractIndexCreationTask<Product>
{
public Products_ByImageCount()
{
Map = products => from product in products
select new
{
Images_Count = product.Images.Count()
};
}
}

_session.Query<Product, Products_ByImageCount>().Where(p =>
p.Images.Count == 0)

Note the parenthesis on the count, invoking the Enumerable.Count() in
the index map. The query still uses it without the parenthesis to
match the index field name.

And no, it doesn't work if you just add parenthesis to your original
query. That's part of the bug.

Matt Johnson

unread,
Dec 11, 2012, 2:55:51 PM12/11/12
to ravendb

mare

unread,
Dec 11, 2012, 3:52:30 PM12/11/12
to rav...@googlegroups.com
Hey Matt, thanks for the explanation and workaround. I was thinking what the heck I'm doing wrong again;)

Oren Eini (Ayende Rahien)

unread,
Dec 12, 2012, 10:44:11 AM12/12/12
to rav...@googlegroups.com
Matt,
This isn't really a bug. Or rather, it is a problem with serialization. We don't make distinctions between dictionaries and objects.
And what should be the behavior if you have:

p.Images["Count"] = 0;

Then exeucte:


      var imagelessProducts = _session.Query<Product>().Where(p=>p.Images.Count == 0).ToList();

mare

unread,
Dec 13, 2012, 10:12:30 AM12/13/12
to rav...@googlegroups.com
Oren, I don't quite get it what you're saying.
 
What am I to do now? Stick with the workaround and wait for this to be fixed (when?) or do something else?

Chris Marisic

unread,
Dec 13, 2012, 10:21:08 AM12/13/12
to rav...@googlegroups.com
Oren is saying RavenDB is not capable of inferring that p=>p.Images.Count == 0 really means to do Enumerable.Count(p.Images) because p.Images.Count could be a legitimate object model. Data in RavenDB is untyped.

He was stating it is not a work around but one of a few numerous ways that you can achieve the intent you're looking for.

Another solution which is probably what I would employ would be to take my model

Product {
List<Image> Images {get;set;}

int ImagesCount  { get { return (Images ?? new List<Image>()).Count; } }

}

And then query against Product.ImagesCount

Matt Johnson

unread,
Dec 13, 2012, 10:59:50 AM12/13/12
to ravendb
I get that part of it, but there's still a bug that you can't express
Enumerable.Count() or .Count() against a dictionary when using a
dynamic linq query.

In other words, if you use .Where(p=> p.Images.Count() == 0), it
doesn't work at all, and it should. If you go into the raven studio
and modify the dynamic index that raven built, change it out for
Enumerable.Count() there and it works. If it was just a problem with
the server-side query execution, then it shouldn't work at all. So
the part of the bug that can be fixed is in the client-side linq query
translator.

Chris Marisic

unread,
Dec 13, 2012, 11:02:48 AM12/13/12
to rav...@googlegroups.com
I agree that Where(p=> p.Images.Count() == 0) should indeed be supported.

Oren Eini (Ayende Rahien)

unread,
Dec 17, 2012, 6:17:56 AM12/17/12
to rav...@googlegroups.com
A pull request for that would be great.
Reply all
Reply to author
Forward
0 new messages