Frage

Ich erhalte einen Kompilierungszeitfehler beim Kompilieren des folgenden Codes und ich kann nicht sehen, warum:

Beziehungen sind viele zu vielen Beziehungen

 var contacts = groups_to_querry
                .SelectMany(x => x.Contacts)
                .Where(x => x.ID == Guid.Empty)
                .SelectMany(p => p.ContactDetails)
                .Where(x => x.ID == Guid.Empty)
                .SelectMany(x => x.Contacts);  //This line gives me a compile time error 
                //Error : The Type argumetns for method 'System.Linq.Enumerable.SelectMany<TSource,Tresult>
                //(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,
                //System.Collections.Generic.IEnumerable<TResult>>)' cannot be infrred from the usage.  
                //Try specifying the type arguments explicitly
War es hilfreich?

Lösung

Das zweite Mal, dass Sie anrufen .SelectMany(x => x.Contacts), Sie arbeiten derzeit mit einer Sammlung von ContactDetails. Es ist zweifelhaft, dass Sie in der Lage sein würden, sie zu verwenden SelectMany darauf. Sie müssten verwenden Select stattdessen.

SelectMany wird verwendet, wenn Sie mehrere Elementkollektionen auswählen und in einen einsetzen möchten IEnumerable. Select wird auf einzelnen Feldern verwendet. Da arbeiten Sie mit Objekten vom Typ ContactDetail (Ich gehe davon aus, dass ich nur einen Kontakt haben kann), Sie würden verwenden Select

Bearbeiten: Hier ist was Sie auf den Punkt gebracht haben, Schritt für Schritt:

groups_to_querry.SelectMany(x => x.Contacts): Aus allen Gruppen, die ich abfragen möchte, wählen Sie alle ihre vielen Kontakte aus. Jede Gruppe hat viele Kontakte, also setzen Sie sie alle in eine einzelne IEnumerable Sammlung von Typ Contact

.Where(x => x.ID == Guid.Empty): ... aber nur diese Kontakte mit einer leeren ID

.SelectMany(p => p.ContactDetails): Wählen Sie dann alle Kontaktdetails von diesen Kontakten aus. Jeder Kontakt hat viele Kontaktdetails, also geben Sie sie alle in einen einzigen IEnumerable Sammlung von Typ ContactDetail

.Where(x => x.ID == Guid.Empty): ... aber nur diese Kontaktdetails mit einer leeren ID

.SelectMany(x => x.Contacts);: Wählen Sie nun die vielen Kontakte der ContactDetails aus. Da der Compiler jedoch weiß, dass es eine Eins-zu-Viele-Beziehung zwischen Kontakten und Kontaktdetails (und nicht umgekehrt) gibt, ist diese Aussage nicht möglich und zeigt somit einen Kompilierfehler an

Andere Tipps

Ich interpretiere Ihre beabsichtigte Abfrage als "Aus mehreren Gruppen von Kontakten, wählen Sie alle Kontakte mit ID = Guid.Empty aus und haben auch Details, die alle ID = Guid.Empty haben".

Die Art und Weise, wie Ihr Code tatsächlich interpretiert wird, lautet "von allen Kontakten, die GUID.Empty haben, alle Details mit GUID.Empty und aus diesen Details alle Kontakte auswählen". Das erste Problem ist, dass Sie am Ende aus Details auswählen. Das bedeutet das Finale SelectMany sollte a sein Select, Weil x.Contacts Hier bezieht sich die vielen zu eins von Details bis hin zu Kontakten.

Das zweite Problem ist, dass das Ergebnis Duplikate von Kontakten enthält, da der gleiche Kontakt für jede Details enthalten ist. Was Sie stattdessen tun sollten, ist die direkte Filterung der Kontakte auf der Grundlage ihrer Detailssammlungen wie folgt:

groups_to_query
.SelectMany(g => g.Contacts)
.Where(c => c.ID == Guid.Empty)
.Where(c => c.ContactDetails.All(d => d.ID == Guid.Empty))

Beachten Sie, dass dies auch Kontakte mit null Details auswählen würde, was ein anderes Verhalten als Ihre Abfrage darstellt. Ich bin mir also nicht sicher, ob es das ist, was Sie wollen. Sie könnten einen weiteren Filter für hinzufügen ContactDetails.Any() wenn nicht.

Bearbeiten: Da Sie Entity Framework verwenden, wird die oben genannte wahrscheinlich nicht funktionieren. Möglicherweise müssen Sie die Details in einer Unterabfrage auswählen und dann nach Ausführung im Speicher filtern:

var queryResult =
    groups_to_query
    .SelectMany(g => g.Contacts)
    .Where(c => c.ID == Guid.Empty)
    .Select(c => new {
        contact = c,
        detailIDs = c.ContactDetails.Select(d => d.ID)
    }).ToList();

var contacts =
    queryResult
    .Where(r => r.detailIDs.All(id => id == Guid.Empty))
    .Select(r => r.contact);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top