2009-05-26 5 views
33

Estoy intentando completar una lista desplegable con compañías farmacéuticas, como Bayer, Medley, etc. Y, estoy obteniendo estos nombres de DB y tesis los nombres se repiten en DB, pero con diferentes id.Linq Distinct() por nombre para completar una lista desplegable con nombre y valor

Estoy tratando de usar Linq Distinct(), pero no quiero usar el comparador de igualdad. ¿Hay otra manera?

Mi lista desplegable debe llenarse con la identificación y el nombre de la empresa.

Estoy intentando algo como: empresas

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

Esta es mostrar repite en DDL.

gracias!

+0

Si una empresa aparece varias veces con diferentes identificadores y desea que aparezcan solo una vez, ¿qué identificación debería mostrarse? ¿El primero? No importa? –

+0

El ID es la identidad – AndreMiranda

Respuesta

76

La siguiente expresión seleccionará sólo las compañías distintas y devolver la primera aparición con su identificación.

partnerService.SelectPartners().GroupBy(p => p.Name).Select(g => g.First()); 
+0

Hola Daniel! ¡Eso era exactamente lo que necesitaba! ¡Gracias! :-) – AndreMiranda

+0

¡Simplemente perfecto! :) – rafek

+0

cuando lo hago: dgvRecords.DataSource = (desde g en dbContext.records seleccione g) .GroupBy (g => g.ID). Seleccione (g => g.FirstOrDefault()); Obtengo: Mensaje = El método especificado no es compatible. Fuente = MySql.Data.Entity –

3

Distinto trabaja en la selección completa. Si incluye c.codPartner en la selección, y hay dos valores diferentes de c.codPartner para el mismo c.nombre, verá dos filas con el mismo c.nombre.

0

simplemente pase en su propio comparador al método Distinct usando una de las otras sobrecargas.

(extension) IQueryable<T> IQueryable<T>.Distinct(IEqualityComparer<T> comparer) 
+0

No cambiará nada ... si hay varias compañías con el mismo nombre pero con una identificación diferente, ¿cómo elegirías la identificación que usarías? –

+0

estoy de acuerdo - elegir la ID sería un problema. Si desea una ID específica para cada uno, usar un distinct con EqualityComparer probablemente no sea el camino a seguir. Además, tenga en cuenta en el voto negativo aquí que la pregunta original no dice nada acerca de elegir una identificación específica para cada artículo en los resultados distintos ... –

1

Si no se especifica un parámetro IEqualityComparer, entonces sólo tiene que utilizar Object.ReferenceEquals, que se ve en el valor de los objetos GetHashKey. Para tipos anónimos, son únicos.

Ahora resolver esto es un poco complicado, ya que no se puede escribir un IEqualityComparer para un tipo anónimo. Por lo que muct crear un tipo real para el problema:

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(); 
+0

ReferenceEquals no compara hashcodes, compara referencias ... devuelve verdadero solo si las dos referencias apuntan a la misma instancia –

2

No creo que se puede hacer esto con una clase anónima, pero si ha creado un objeto de datos como

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

} 

puede crear un objeto como comparador

class FooComparer : IEqualityComparer<Foo> 
{ 


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

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

} 
17
var distinctCompanies = Companies 
    .GroupBy(c => c.CompanyName) 
    .Select(g => g.First()); 
+0

lo siento preguntar, pero ¿de dónde es la 'g'? – StarCub

+1

@StarCub Companies es un IEnumerable . GroupBy acepta eso y devuelve IEnumerable >. Cada elemento en Select es un IGrouping . Usé un nombre diferente para hacer la diferencia en el tipo más obvio. –

1

distinc utilizará GetHashCode si no te dirá que (a través de un IEqualityComparer) a usa otro método Se puede usar un EqualityComparer genérico, como esto:

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 
} 

y luego usar como esto (tipode)

public static IEqualityComparer<YourType> MyComparer 
{ 
    get 
    { 
     return new GenericEqualityComparer<YourType>((x, y) => 
     { 
      return x.name.Equals(y.name); 
     }); 
     } 
} 
Cuestiones relacionadas