views:

4903

answers:

7

Hi!

I'm trying to populate a Drop down list with pharmaceutical companies, like Bayer, Medley etc. And, I'm getting theses names from DB and theses names are repeated in DB, but with different id's.

I'm trying to use Linq Distinct(), but I don't want to use the equality comparer. Is there another way?

My drop down list must be filled with the id and the name of the company.

I'm trying something like:

var x = _partnerService.SelectPartners().Select(c => new {codPartner = c.codPartner, name = c.name}).Distinct();

This is showing repeated companies in ddl.

thanks!

+1  A: 

Distinct works on the entire select. If you include c.codPartner in the select, and there are two different values of c.codPartner for the same c.name, then you are going to see two rows with the same c.name.

Robert Harvey
A: 

just pass in your own comparer to the Distinct method using one of the other overloads.

(extension) IQueryable<T> IQueryable<T>.Distinct( IEqualityComparer<T> comparer )
Scott Ivey
It won't change anything... if there are several companies with the same name but different id, how would you choose the id to use ?
Thomas Levesque
i agree - choosing the ID would be a problem. If you want a specific ID for each, using a distinct with an EqualityComparer probably wouldn't be the way to go. Also, keep in mind on the downvote here that the original question said nothing about picking a specific ID for each item in the distinct results...
Scott Ivey
A: 

If you do not specify a IEqualityComparer parameter, then it will just use Object.ReferenceEquals, which looks at the objects GetHashKey value. For anonymous types, they are unique.

Now solving this is a bit tricky, since you cannot write an IEqualityComparer for an anonymous type. So you muct create a real type for the problem:

class Partner
{
    public int codPartner {get; set;}
    public string name {get; set;}
    public override int GetHashCode() { return name .GetHashCode();}
}

var x = _partnerService.SelectPartners()
        .Select(c => new Partner {codPartner = c.codPartner, name = c.name})
        .Distinct();
James Curran
ReferenceEquals doesn't compare hashcodes, it compares references... it will return true only if the two references point to the same instance
Thomas Levesque
+1  A: 

I don't think you can do this with an anonymous class, but if you created a data object like

    class Foo
{
    private int _ID;

    public int ID
    {
        get { return _ID; }
        set { _ID = value; }
    }
    private string _Name;

    public string Name
    {
        get { return _Name; }
        set { _Name = value; }
    }

}

you could create a comparer object like

    class FooComparer : IEqualityComparer<Foo>
{


    public bool Equals(Foo x, Foo y)
    {
        return x.Name == y.Name;
    }

    public int GetHashCode(Foo obj)
    {
        return obj.GetHashCode();
    }

}
wegrata
+5  A: 
var distinctCompanies = Companies
  .GroupBy(c => c.CompanyName)
  .Select(g => g.First());
David B
+1  A: 

Distinc will use GetHashCode if you don´t tell it (via an IEqualityComparer) to use another method. You could use a generic equalitycomparer, like this:

public class GenericEqualityComparer<T> : IEqualityComparer<T>
{    
    private Func<T, T, Boolean> comparer;    

    public GenericEqualityComparer(Func<T, T, Boolean> comparer)    
    {        
        this.comparer = comparer;    
    }    

    #region IEqualityComparer<T> Implementation

    public bool Equals(T x, T y)    
    {        
        return comparer(x, y);    
    }    

    public int GetHashCode(T obj)    
    {
        return obj.GetHashCode();  
    }    

    #endregion
}

and then use like this (kindof)

public static IEqualityComparer<YourType> MyComparer
{
   get
     {
      return new GenericEqualityComparer<YourType>((x, y) =>
       {
          return x.name.Equals(y.name);
        });
      }
}
Johan Leino
+9  A: 

The following expression will select only distinct companies and return the first occurence with its id.

partnerService.SelectPartners().GroupBy(p => p.Name).Select(g => g.First());
Daniel Brückner
Hi Daniel! That was exactly what I needed! Thanks! :-)
AndreMiranda
Just perfect! :)
rafek