2009-05-26 6 views
33

Próbuję wypełnić listę rozwijaną firmami farmaceutycznymi, takimi jak Bayer, Medley itp. I, otrzymuję tezy od DB i tezy nazwy są powtarzane w DB, ale z różnymi identyfikatorami.Linq Distinct() według nazwy dla zapełnienia listy rozwijanej o nazwie i wartości

Próbuję użyć Linq Distinct(), ale nie chcę używać porównywania równości. Czy istnieje inny sposób?

Moja lista rozwijana musi być wypełniona identyfikatorem i nazwą firmy.

Próbuję coś takiego:

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

To pokazuje powtarzanych przedsiębiorstwa w DDL.

dziękuję!

+0

Jeśli firma pojawia się wiele razy z różnymi numerami identyfikacyjnymi i chcesz, aby pojawiały się tylko raz, jaki identyfikator powinien być wyświetlany? Pierwszy? Nie ma znaczenia? –

+0

Identyfikator jest tożsamością – AndreMiranda

Odpowiedz

76

Poniższe wyrażenie będzie wybrać tylko odrębne przedsiębiorstwa i powrót pierwszego wystąpienia z jego id.

+0

Cześć Daniel! To było dokładnie to, czego potrzebowałem! Dzięki! :-) – AndreMiranda

+0

Po prostu idealne! :) – rafek

+0

kiedy to zrobię: dgvRecords.DataSource = (z g w dbContext.records wybierz g) .GroupBy (g => g.ID). Wybierz (g => g.FirstOrDefault()); Otrzymuję: Message = Określona metoda nie jest obsługiwana. Źródło = MySql.Data.Entity –

3

Wyraźne działa na cały zaznaczony. Jeśli umieścisz c.codPartner w selekcji i istnieją dwie różne wartości c.codPartner dla tego samego c.name, zobaczysz dwa wiersze o tej samej nazwie c.nazwa.

0

Wystarczy przekazać własny porównywal do metody Distinct, używając jednego z innych przeciążeń.

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

Nie zmieni niczego ... jeśli istnieje kilka firm o tej samej nazwie, ale o różnych identyfikatorach, w jaki sposób wybrałbyś identyfikator do użycia? –

+0

Zgadzam się - wybór ID byłby problemem. Jeśli potrzebujesz konkretnego identyfikatora dla każdego, użycie odrębnego z EqualityComparer prawdopodobnie nie byłoby drogą do zrobienia. Pamiętaj też, że oryginalne pytanie nie mówiło nic o wybraniu konkretnego identyfikatora dla każdego elementu w różnych wynikach ... –

1

Jeśli nie zostanie określony parametr IEqualityComparer, to będzie po prostu użyć Object.ReferenceEquals, który patrzy na obiektach wartości GetHashKey. W przypadku typów anonimowych są unikatowe.

Rozwiązaniem tego problemu jest nieco trudność, ponieważ nie można napisać IEqualityComparer dla anonimowego typu. Więc muct utworzyć prawdziwy typ dla problemu:

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

Element ReferenceEquals nie porównuje kodów skrótu, porównuje odwołania ... Zwróci true tylko wtedy, gdy dwa odwołania wskazują na to samo wystąpienie. –

2

I nie sądzę, że można to zrobić za pomocą anonimowej klasy, ale po utworzeniu obiektu danych jak

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

} 

można tworzyć obiekt comparer jak

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

Przykro mi to pytać, ale gdzie jest literka "g"? – StarCub

+1

@StarCub Companies to IEnumerable . GroupBy akceptuje to i zwraca IEnumerable >. Każda pozycja w Select to IGrouping . Użyłem innej nazwy, aby różnica w typie była bardziej oczywista. –

1

distinc użyje GetHashCode jeśli jeszcze nie powiedzieć go (poprzez IEqualityComparer) do użyj innej metody. Można użyć rodzajowe equalitycomparer, tak:

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 
} 

a następnie użyć tak (kindof)

public static IEqualityComparer<YourType> MyComparer 
{ 
    get 
    { 
     return new GenericEqualityComparer<YourType>((x, y) => 
     { 
      return x.name.Equals(y.name); 
     }); 
     } 
} 
Powiązane problemy