Ieri stavo lavorando a un refactor del codice e ho trovato un'eccezione su cui non sono riuscito a trovare molte informazioni. Ecco la situazioneEccezione nella query Inner LINQ quando si chiama ToList()
Abbiamo una coppia di entità EF che hanno una relazione molte a molte attraverso una tabella delle relazioni. Gli oggetti in questione assomigliano a questo, tralasciando i bit non necessari.
public partial class MasterCode
{
public int MasterCodeId { get; set; }
...
public virtual ICollection<MasterCodeToSubCode> MasterCodeToSubCodes { get; set; }
}
public partial class MasterCodeToSubCodes
{
public int MasterCodeToSubCodeId { get; set; }
public int MasterCodeId { get; set; }
public int SubCodeId { get; set; }
...
}
Ora, ho tentato di eseguire una query LINQ contro queste entità. Utilizziamo molte proiezioni LINQ in DTO. Seguono il DTO e la query. masterCodeId è un parametro passato in.
public class MasterCodeDto
{
public int MasterCodeId { get; set; }
...
public ICollection<int> SubCodeIds { get; set; }
}
(from m in MasterCodes
where m.MasterCodeId == masterCodeId
select new MasterCodeDto
{
...
SubCodeIds = (from s in m.MasterCodeToSubCodes
select s.SubCodeId).ToList(),
...
}).SingleOrDefaultAsync();
La query interna getta la seguente eccezione
Expression of type 'System.Data.Entity.Infrastructure.ObjectReferenceEqualityComparer' cannot be used for constructor parameter of type 'System.Collections.Generic.IEqualityComparer`1[System.Int32]'
Abbiamo fatto domande interne di simile prima in altri luoghi nel nostro codice e non ha avuto problemi. La differenza in questo è che non stiamo rinnovando un oggetto e proiettandolo ma piuttosto restituendo un gruppo di ints che vogliamo inserire in un elenco.
Ho trovato una soluzione alternativa modificando ICollection su MasterCodeDto in IEnumerable e rilasciando ToList() ma non sono mai riuscito a scoprire perché non potevo semplicemente selezionare gli ID e restituirli come elenco.
Qualcuno ha qualche idea in merito a questo problema? Normalmente restituendo solo un campo id e chiamando ToList() funziona bene quando non fa parte di una query interna. Mi manca una restrizione sulle query interne che impedisce che un'operazione come questa accada?
Grazie.
Modifica: per dare un esempio di dove questo schema funziona, ti mostrerò un esempio di una query che funziona.
(from p in Persons
where p.PersonId == personId
select new PersonDto
{
...
ContactInformation = (from pc in p.PersonContacts
select new ContactInformationDto
{
ContactInformationId = pc.PatientContactId,
...
}).ToList(),
...
}).SingleOrDefaultAsync();
In questo esempio, stiamo selezionando un nuovo Dto anziché selezionare un singolo valore. Funziona bene. I problemi sembrano derivare dalla semplice selezione di un singolo valore.
Modifica 2: in un altro aspetto divertente, se invece di selezionare in un MasterCodeDto seleziono in un tipo anonimo, l'eccezione non viene generata con ToList() sul posto.
Sei davvero sicuro che sia l''elenco degli utenti() 'a causare l'errore? – flindeberg
Se rimuovo il ToList() l'eccezione scompare e ho appena ricevuto errori di cast tra IEnumerable e ICollection . Se cambio ICollection in IEnumerable elimina questo errore. –
Anche quando lo enumerate in seguito? – flindeberg