Class,anonymous类型和SelectListItem上的Distinct()

时间:2010-03-02 09:43:47

标签: asp.net-mvc linq-to-entities distinct

我想从网络服务中选择所有类别。 web服务没有方法,所以我必须获取所有产品,然后选择这些产品所在的所有类别。当我从webservice接收数据时,我制作WebServiceProduct(ID,Name等)和WebServiceCategory(它的ID,名称等对象。

这不起作用:

        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);

但是当我第一次选择它作为匿名类型时,它会起作用:

        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
                                                };

我还尝试使用IEqualityComparer并覆盖了Equals和GetHashCode以检查WebServiceCategory.ID,但它也不起作用。

所以我的问题是,为什么Distinct()在anonymus类型上比在我的WebServiceCategory对象和SelectListItem上工作得更好?

3 个答案:

答案 0 :(得分:2)

匿名类型具有值相等性。引用类型具有引用相等性。 LINQ to Entities遵循类型的默认语义。但是覆盖Equals或实现IEquatable将不起作用,因为LINQ to Entities查询被转换为SQL,而LINQ to Entities无法将任意C#代码转换为SQL。请注意,例如Distinct的重载采用了比较器aren't supported in L2E

在第二个代码示例中,您已经有一个解决方法。另一种方法是按匿名类型分组:

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
                 };

答案 1 :(得分:0)

您是否尝试在IEquatable<T>上实施SelectListItem

答案 2 :(得分:0)

我认为,它是一个IQueryable对象,IEqualityComparer不适用于这个对象。也许这会有所帮助

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
                                         });