Announcement

Collapse
No announcement yet.

Group by bei Linq

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Group by bei Linq

    Hallo Forum,

    ich habe folgendes Problem. Ich habe eine Tabelle die etwa wie folg aufgebaut ist:
    Tablle "MyTable"
    PersonId, Name, Abteilung, Adresse
    1 | a | 1 | abc
    2 | x | 2 | igd
    1 | r | 3 | hfgd
    3 | a | 1 | abc
    2 | x | 2 | igd
    1 | r | 3 | hfgd

    ich brauche nun eine Linq-Abfrage, die die Informationen groupiert und mir diese wie folge zurückgibt.
    PersonId, Anzahl
    1 | 3
    2 | 2
    3 | 1

    Dafür habe ich diese Methode:

    Code:
            public IQueryable<MyTable> getGroups()
            {
                return from p in MyTable
                       orderby p.PersonId
                       group p by p.PersonId into grp
                       select new MyTable { PersonId = grp.Key, Anzahl = grp.Count()};
            }
    Das funktioniert leider nicht (Fehlermeldung: Die explizite Konstruktion des Entitätstyps "PVAdministration.Models.MyTable" in einer Abfrage ist unzulässig.). Wahrscheinlich, weil es in der Tabelle kein Feld namens "Anzahl" gibt. Ich brauche Dazu auch alle anderen Felder. Ist das möglich?

    Danke im Voraus.
    Zuletzt editiert von Smart; 13.09.2013, 11:01.

  • #2
    Hallo,

    ist es Linq2Sql od. das Entity Framework?

    Sollte sich eine Operation nicht entsprechend nach SQL übersetzen lassen, wie es hier der Fall ist, so kannst du die Query vorher materialisieren. D.h. hier nach dem GroupBy ein ToList durchführen, dann kannst du lokal mit Linq2Objects die Query beliebig weiter bearbeiten.

    BTW: Das orderby ist vor dem groupby nicht unbedingt nötigt. Sorge dann bei der weiteren Verarbeitung für die korrekte Sortierung.

    mfG Gü
    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

    Comment


    • #3
      Hi,

      danke für deine Antwort.
      Das ist eine Linq2Sql. Ehrlich gesagt, ist mir das Ganze immer noch nicht ganz klar. Kannst du mir bitte die Abfrage oben so modifizieren, wie du das meinst? Ich habe das hier versucht. Da werden die Felder (wie Anzahl) immer nich nicht erkannt.

      public IQueryable<MyTable> getGroups()
      {
      return from p in MyTable
      orderby p.PersonId
      group p by p.PersonId.ToList() into grp
      select new MyTable { PersonId = grp.Key, Anzahl = grp.Count()};
      }

      Die Fehlermeldung mit "Die explizite Konstruktion des Entitätstyps "PVAdministration.Models.MyTable" in einer Abfrage ist unzulässig" ist nach wie vor vorhanden. Ich einer Hilfsklasse funktioniert es aber einigermassen.

      Danke im Voraus.

      Comment


      • #4
        Wieso select new MyTable? MyTable hat nach deinen Angaben die Felder PersonId, Name, Abteilung, Adresse aber kein Anzahl. Also kann aus deiner Abfrage kein MyTable rausfallen sondern entweder ein anonymer Typ oder ein von dir angelegter anderer Typ der auch ein Anzahl Feld hat.

        Comment


        • #5
          Hallo Ralf,

          vielen Dank für deine Antwort. Ich habe das Problem mit einer Hilfsklasse gelöst. Ich verstehe aber nicht, warum ich innerhalb von "select new MyTable" nicht auf "p" zugreifen kann. Das "p" ich nämlich innerhalb von {} unbekannt. Gibt es einen Weg, auf "p" trotzdem zuzugreifen?

          Gruß

          Comment


          • #6
            Das "p" ich nämlich innerhalb von {} unbekannt. Gibt es einen Weg, auf "p" trotzdem zuzugreifen?
            Gegenfrage auf welches p denn? Nach dem Gruppieren sagen wir mal von 7 Datensätzen mit gleicher PersonID (also mit Count 7) hättest du ja 7 verschiedene p Datensätze. Wenn ein Zugriff auf p.Name noch möglich wäre welchen der 7 möglicherweise verschiedenen Namen sollte denn da kommen?

            Du kannst nur auf Dinge zugreifen nach denen du auch gruppiert hast.
            Da das haargenau so wie in SQL ist versuche ich das nochmal über SQL zu erklären da haben die meisten mehr Vorwissen. Eventuell kannst du das dann auch besser mappen

            Du hast ja nur nach PersonID gruppiert und dir den Count geben lassen.
            In SQL etwa

            [Highlight=SQL]select PersonId, count(*) from MyTable group by PersonId[/Highlight]

            Du könntest jetzt auf keinen Fall im Select auch z.B. auf Name aus MyTable zurückgreifen. Da nur nach PersonID gruppiert wurde sind ja alle Datensätze mit gleicher PersonID aber ansonsten unterschiedlichen Daten zu einem Datensatz zusammengefasst worden. Also aus welchem ursprünglichen MyTable Datensatz sollte den der Name kommen wenn man in da auch angeben können. Wenn ich 100 Datensätze zu einem zusammenfassen könnten das auch 100 verschiedene Namen sein. Wenn du also auch den Namen brauchst müßtest du auch danach gruppieren.
            AKA

            [Highlight=SQL]select PersonId, Name, count(*) from MyTable group by PersonId, Name[/Highlight]

            Und die selbe Option hast du auch in LINQ. Du musst alle Felder die du nachher verwenden willst auch im Key unterbringen um danach zu gruppieren.

            [Highlight=C#]
            from p in MyTable
            orderby p.PersonId
            group p by new { p.PersonId, p.Name } into grp
            select new { PersonId = grp.Key.PersonId, Name = grp.Key.Name, Anzahl = grp.Count()};
            [/Highlight]

            Aber bedenke wenn es je PersonID tatsächlich unterschiedliche Namen gibt dann bekommst du jetzt ein anderes weiter heruntergebrochendes Ergebnis. Wenn das auch in deinem konkreten Fall passieren führen hattest du aber eh ein prinzipiellen Denkfehler wenn du innerhalb des select noch auf p zugreifen willst.

            Comment


            • #7
              Hallo Ralf,

              danke. Ich habe jetzt verstanden, wie die Abfrage aussehen muss. Ich fange gerade an, richtig mit LINQ zu arbeiten und habe noch ein paar Probleme, einige Sache zu begreifen. Besonders die Sache mit "new". Ich wieß nicht ganz genau, wann dies zum Einsatz kommt. Meine eigentliche Tabelle hat viele andere Felder. Diese Tabelle sollte nur ein Beispiel sein.

              Gruß

              Comment

              Working...
              X