views:

188

answers:

3

I want to select all categories from a webservice. The webservice does not have a method for that, so I have to get all products, then select all categories that these products are in. When I recieve the data from the webservice, I make WebServiceProduct (ID, Name, etc) and WebServiceCategory (ID, Name, etc) objects of it.

This does not work:

        IQueryable<SelectListItem> categories = (from p in webserviceProductRepository.GetProducts()
                                                 from c in p.Categories
                                                 select new SelectListItem
                                                 {
                                                     Value = c.ID.ToString(),
                                                     Text = c.Name
                                                 }).Distinct().OrderBy(c => c.Text);

But it works when I first select it as a anonymus type:

        var foo = (from p in webserviceProductRepository.GetProducts()
                   from c in p.Categories
                   select new
                   {
                       ID = c.ID.ToString(),
                       Name = c.Name
                   }).Distinct().OrderBy(c => c.Name);

        IQueryable<SelectListItem> categories = from c in foo
                                                select new SelectListItem
                                                {
                                                    Value = c.ID.ToString(),
                                                    Text = c.Name
                                                };

I have also tried with a IEqualityComparer and overrided Equals and GetHashCode to check on WebServiceCategory.ID, but it does not work either.

So my question are, why is Distinct() working better on a anonymus type than on my WebServiceCategory object and SelectListItem?

A: 

Have you tried implementing IEquatable<T> on SelectListItem?

Gabe
No, I have not, will try that later.
Johan Olsson
A: 

I think, its an IQueryable object and IEqualityComparer's wont work for this object. Maybe this will help

IQueryable<SelectListItem> categories = (from p in webserviceProductRepository.GetProducts()
                                         from c in p.Categories.Distinct()
                                         orderby c.Name
                                         select new SelectListItem
                                         {
                                             Value = c.ID.ToString(),
                                             Text = c.Name
                                         });
cem
Already tried this and it does not work.
Johan Olsson
I think, If web service - or repository does not distinct values via this code. You have to get values to memory, after distinct values. Whats the 'foo' type when you use anonymous types?
cem
+1  A: 

Anonymous types have value equality. Reference types have reference equality. LINQ to Entities is following the default semantics for the types. But overriding Equals or implementing IEquatable won't work, because LINQ to Entities queries are translated to SQL, and LINQ to Entities cannot translate arbitrary C# code to SQL. Note that the overloads of, e.g., Distinct which take a comparer aren't supported in L2E.

You have one workaround already, in your second code example. Another would be to group by an anonymous type:

var categories = from p in webserviceProductRepository.GetProducts()
                 from c in p.Categories
                 group c by new { Id = c.ID, Name = c.Name } into g
                 order by g.Key.Name
                 select new SelectListItem
                 {
                     Value = g.Key.Id.ToString(),
                     Text = g.Key.Name
                 };
Craig Stuntz