none
Linq und Distinct() RRS feed

  • Frage

  • Hallo! Ich habe eine Frage zu LINQ.

    Ich habe ein ObjectContext (RIA, DomainService, generiert aus einem
    Model im Web-Project), weches mir ein ObjectSet<PersonView> liefert.
    Eine PersonView besteht aus Daten einer Person (z.B. Lastname,
    Firstname).
    Es kann vorkommen, dass die Kombination aus Lastname und Firstname
    mehrmmals auftaucht, und so auch im OjectSet mehrmals auftaucht. Aber
    ich möchte, dass die Methode "GetPersonViewByName" diese Kombination
    nur einmal liefert (distinct).

    So etwas hilft aber nicht:

    public IQueryable<PersonView> GetPersonViewByName(string part)
            {
                return  (from item in this.ObjectContext.PersonView
                        where item.Lastname.StartsWith(part)
                        || item.Lastname.EndsWith(part)
                        || item.Firstname.StartsWith(part)
                        || item.Firstname.EndsWith(part)
                         select item).Distinct();
            }

    Okay, klar. Ich vergleiche auch die von mir erstelten Objekte, also
    muss ich einen "EqualityComparer" schreiben.

    public class Equaler : IEqualityComparer<AllowanceView>
        {
            public bool Equals(PersonView x, PersonView y)
            {
                if (Object.ReferenceEquals(x, y))
                    return true;
                if (Object.ReferenceEquals(x, null) ||
    Object.ReferenceEquals(y, null))
                    return false;
                return x.Partnernr == y.Partnernr;
            }

            public int GetHashCode(PersonView x)
            {
                if (Object.ReferenceEquals(x, null))
                    return 0;
                return x.GetHashCode();
            }

        }

    Ich verwende dies Klasse dann so:

    public IQueryable<PersonView> GetPersonViewByName(string part)
            {
                return  (from item in this.ObjectContext.PersonView
                        where item.Lastname.StartsWith(part)
                        || item.Lastname.EndsWith(part)
                        || item.Firstname.StartsWith(part)
                        || item.Firstname.EndsWith(part)
                         select item).Distinct(new Equaler());
            }

    Aber auch jetzt ist das ergenis nicht distinct.
    Auch in diesem Falle nicht:

    public IQueryable<PersonView> GetPersonViewByName(string part)
            {
                return  (from item in
    this.ObjectContext.PersonView.Distinct(new Equaler)
                        where item.Lastname.StartsWith(part)
                        || item.Lastname.EndsWith(part)
                        || item.Firstname.StartsWith(part)
                        || item.Firstname.EndsWith(part)
                         select item);
            }

    Was mache ich falsch? Ist der EqualityComparer nicht richtig
    geschrieben?

    Danke für die Hilfe!

    Donnerstag, 13. Januar 2011 18:31

Antworten

Alle Antworten

  • Am 13.01.2011 19:31, schrieb Dulcine2008:

    Es kann vorkommen, dass die Kombination aus Lastname und Firstname
    mehrmmals auftaucht, Aber ich möchte, dass die Methode diese Kombination nur einmal liefert (distinct).

    public IQueryable<PersonView>  GetPersonViewByName(string part)
             {
                 return  (from item in this.ObjectContext.PersonView
                         where item.Lastname.StartsWith(part)
                         || item.Lastname.EndsWith(part)
                         || item.Firstname.StartsWith(part)
                         || item.Firstname.EndsWith(part)
                          select item).Distinct();
             }

    Okay, klar. Ich vergleiche auch die von mir erstelten Objekte, also
    muss ich einen "EqualityComparer" schreiben.

    public class Equaler : IEqualityComparer<AllowanceView>
         {
             public bool Equals(PersonView x, PersonView y)
             {
                 if (Object.ReferenceEquals(x, y))
                     return true;
                 if (Object.ReferenceEquals(x, null) ||
    Object.ReferenceEquals(y, null))
                     return false;
                 return x.Partnernr == y.Partnernr;
             }

     

    Du willst ja mehrfache Kombinationen von Lastname und Firstname
    ausschließen, tatsächlich sortiert Du aber nur Mehrfach-Kombinationen
    von Partnernr aus.

    Die letzte Zeile im IEqualityComparer sollte daher lauten:

    bool Equals (...)
    {
     //...
    
     //alt: return x.Partnernr == y.Partnernr; 
     return string.Compare(x.Lastname, y.Lastname) == 0
       && string.Compare(x.Firstname, y.Firstname ) == 0;
    }
    

    evtl noch case-unsensitiv machen.

    Christoph


    Donnerstag, 13. Januar 2011 19:58
  • Hallo D.,

    Linq to Entities hat da mehrere Möglichkeiten. Hier zwei davon:

    1. Wenn Du nur die Kombination zweier Felder ausschließen möchtest:

    var query1 = (from c in northwindEntities.Customers
    	   select new {c.City, c.Country}).Distinct();
    
    

    2. Wenn Du auch anderen Felder zurückgeben möchtest:

    var query2 = (from c in northwindEntities.Customers
    	   group c by new {c.City, c.Country} into g
           select g.FirstOrDefault());
    
    


    Gewusst wie: Entfernen doppelter Elemente aus LINQ to Entities-Abfrageergebnissen:
    http://msdn.microsoft.com/de-de/library/cc716801.aspx

    Gruß
    Marcel

    Donnerstag, 13. Januar 2011 20:24
    Moderator
  • Hallo D.,

    hier ein paar Lösungs-Ansätze und Hinweise:

    [Implementing a DISTINCT clause in LINQ, for your objects « Techkn0w]
    http://techkn0w.wordpress.com/2010/06/09/implementing-a-distinct-clause-in-linq-for-your-objects/

    [c# - Distinct not working with LINQ to Objects - Stack Overflow]
    http://stackoverflow.com/questions/1365748/distinct-not-working-with-linq-to-objects

    [c# - LINQ Get Distinct values and fill LIST - Stack Overflow]
    http://stackoverflow.com/questions/1786770/linq-get-distinct-values-and-fill-list

    [LINQ Farm: Using Distinct and Avoiding Lambdas - Charlie Calvert's Community Blog - Site Home - MSDN Blogs]
    http://blogs.msdn.com/b/charlie/archive/2006/11/19/linq-farm-group-and-distinct.aspx

    [Implement IEquatable to Power Up LINQ Distinct Queries]
    http://www.eggheadcafe.com/sample-code/LINQ/0673e72e-e8e2-459e-bae4-7e0126487093/implement-iequatable-to-power-up-linq-distinct-queries.aspx

     


    ciao Frank
    Freitag, 14. Januar 2011 06:29
  • Danke! Funktioniert vorzüglich!

     

    Samstag, 15. Januar 2011 12:17
  • Hallo Dulcine,

    > Danke! Funktioniert vorzüglich!
    Gerne.

    P.S. Bitte markiere die Antwort(en) die Dir geholfen haben als Antwort.

    Gruß
    Marcel

    Samstag, 15. Januar 2011 15:22
    Moderator