Domanda

Sto ricevendo un errore di tempo di compilazione quando compilo il codice seguente e non riesco a capire perché:

Le relazioni sono molte con molte relazioni

 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
È stato utile?

Soluzione

La seconda volta che chiedi .SelectMany(x => x.Contacts), stai attualmente lavorando con una raccolta di ContactDetails. È dubbio che saresti in grado di usare SelectMany su di esso. Dovresti usare Select invece.

SelectMany viene utilizzato quando si desidera selezionare più raccolte di elementi e inserirle in una IEnumerable. Select viene utilizzato su singoli campi. Dato che stai lavorando con oggetti di tipo ContactDetail (che presumo possa avere solo un contatto), dovresti utilizzare Select

EDIT: ecco cosa stai facendo in poche parole, passo dopo passo:

groups_to_querry.SelectMany(x => x.Contacts): Da tutti i gruppi che voglio interrogare tutti i loro numerosi contatti. Ogni gruppo ha molti contatti, quindi mettili tutti in un singolo IEnumerable Raccolta di tipo Contact

.Where(x => x.ID == Guid.Empty): ... ma solo quei contatti con un ID vuoto

.SelectMany(p => p.ContactDetails): Quindi selezionare tutti i tanti contatti di contatti. Ogni contatto ha molti contactDetails, quindi mettili tutti in un singolo IEnumerable Raccolta di tipo ContactDetail

.Where(x => x.ID == Guid.Empty): ... ma solo quei contactDetails con un ID vuoto

.SelectMany(x => x.Contacts);: Ora seleziona ciascuno dei numerosi contatti dei contatti. Tuttavia, dal momento che il compilatore sa che esiste una relazione da uno a molti contatti e contatti (e non viceversa) tale affermazione non è possibile e quindi mostra un errore di compilazione

Altri suggerimenti

Sto interpretando la tua query prevista come "Da più gruppi di contatti, selezionare tutti i contatti che hanno Id = Guid.Empty e hanno anche dettagli che hanno tutti Id = Guid.Empty".

Il modo in cui viene effettivamente interpretato il tuo codice è "da tutti i contatti che hanno GUID.Empty, selezionare tutti i dettagli che hanno GUID.Empty e da tali dettagli selezionano tutti i contatti". Il primo problema è che finisci per selezionare dai dettagli. Questo significa la finale SelectMany dovrebbe essere un Select, perché x.Contacts Qui si riferisce alla relazione molti-to-one dai dettagli ai contatti.

Il secondo problema è che il risultato conterrà duplicati dei contatti, poiché lo stesso contatto è incluso per ciascun dettaglio. Quello che dovresti fare invece è filtrare i contatti direttamente in base alle loro raccolte di dettagli, in questo modo:

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

Nota questo selezionerebbe anche contatti che hanno dettagli zero, che sono comportamenti diversi dalla tua query, quindi non sono sicuro che sia quello che desideri. Potresti aggiungere un altro filtro per ContactDetails.Any() altrimenti.

Modificare: Dal momento che stai usando Entity Framework, quanto sopra probabilmente non funzionerà. Potrebbe essere necessario selezionare i dettagli in una sottoquery e quindi filtrare in memoria dopo aver eseguito:

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);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top