Distinct() on Class, anonymus type and SelectListItem
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(),
开发者_如何学C 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?
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
};
Have you tried implementing IEquatable<T>
on SelectListItem
?
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
});
精彩评论