2012-04-18 11 views
6

Vedo un comportamento strano nel mio modello Entity Framework. Ho una query che assomiglia a questo:Il framework Entity restituisce null per una riga se la prima colonna in quella riga è null

var rows = (from alarm in context.Alarms 
      join temp in context.ListDetails on alarm.ListDetailId equals temp.ListDetailId into entries from entry in entries.DefaultIfEmpty() 
      join read in context.Reads  on alarm.ReadId  equals read.ReadId 
      join plate in context.Images  on alarm.ReadId  equals plate.ReadId 
      where alarm.IActive == 1 && ! alarm.TransmittedAlarm 
      where read.IActive == 1 
      where plate.IActive == 1 && plate.ImageTypeId == 2 
      select new { alarm, entry, read, plate }).ToArray(); 

La query restituisce tutte le colonne in ordine alfabetico per nome della colonna. Si scopre che questa colonna è NULL per poche righe nel set di risultati. Quando espongo la variabile rows nel debugger, vedo che l'intera riga è nullo!

MODIFICA: alcuni chiarimenti.

Per "prima colonna", intendo la prima colonna della prima riga, cioè, in "SELEZIONA A, B, C DA ...", intendo A. Accade semplicemente che la query che Entity Framework costruisce restituisce tutte le colonne nel set di risultati uniti in ordine alfabetico e il primo in ordine alfabetico è annullabile ed è nullo per alcune righe.

La colonna in questione non è una chiave primaria; se fosse una chiave primaria, non potrebbe essere nulla.

Quando Entity Framework elabora le righe dei dati restituiti in oggetti, sta esaminando il valore della prima colonna in ogni riga. Se quella colonna è nullo, restituisce null per la riga, invece di un oggetto con la proprietà corrispondente a quella colonna impostata su null.

Non credo che questo abbia qualcosa da fare in particolare con un join esterno sinistro; succede solo che la mia query ne usa uno. Tuttavia, non ho effettuato alcun test per verificarlo, quindi è solo una supposizione.

Qualcuno l'ha visto prima? Qualcuno ha una soluzione per questo?

Tony

+0

Hai bisogno di un join di sinistra? –

+0

In quale luogo si ottiene l'errore? –

+0

Potresti postare la query SQL che l'EF invia al DB? –

risposta

1

Si utilizza DefaultIfEmpty nel vostro ci uniamo. Significa

Se ci sei elementi in entries che corrispondono al criterio di join (alarm.ListDetailId equals temp.ListDetailId), voglio che mettiate un singolo valore di default di tipo ListDetail (che è null) in entries.

In questo caso EF genera un LEFT JOIN. In realtà, questo codice è il modo ben noto per generare un LEFT JOIN con Linq2Sql o EF.

L'istruzione LEFT JOIN seleziona i valori NULL per tutte le colonne della tabella se nessuna riga nella tabella corrisponde al criterio JOIN. In effetti, l'unica colonna che conta è la colonna PK dell'entità. EF verifica se il valore PK è NULL, decide che nessuna entità esiste e inserisce null in entries. Quindi ottieni questo null come valore della proprietà entry dei risultati.

+0

Ho bisogno del join esterno sinistro. Il problema non è che il 'entry' è' NULL'; il problema è che la prima colonna in 'alarm' è' NULL' e l'intero select 'new {alarm, entry, read, plate}' viene restituito come 'NULL', non solo' entry'. –

6

Posso confermare che ho esattamente lo stesso problema: quando la query SQL formata da EF ha null nella prima colonna del risultato, restituisce null invece di entità. Significa esattamente seguendo:

using (var dc = new MyDbContext()) 
{ 
    var q = dc.Lands; //Lands is DbSet<Land> 
    q = q.Where(criteria); //this leads to SQL query returning null in first column, confirmed by profiler 
    var t = q.Single(); //t is now null 
} 

Se prendiamo altri criteri, che non comporti null nella prima colonna, t è normale non null entità.

Mi sembra che si tratti di una sorta di oscuro comportamento/bug in EF.

Aggiornamento

Dopo diverse ore di sondare ho trovato seguente comportamento. EF restituisce null per le entit che hanno NULL nella prima colonna del risultato (che interrompe il comportamento previsto), ma ha diverse nozioni su quale colonna inserire per prima nell'elenco di selezione. Quindi, dopo aver reso il mio modello perfettamente coerente con lo stato del mio database (che indica tutte le colonne del database e sostituendo le proprietà di spostamento required con optional) - Sto usando il Codice, quindi ci sono molti posti per essere espliciti sul database - Sono riuscito a farlo funzionare.

Significa che è necessario controllare la definizione a livello di negozio del modello (a seconda del paradigma utilizzato, basato sul progettista o basato sul codice, sarebbe diverso) rispetto al database.

Problemi correlati