2012-04-11 10 views
11

Recentemente ho ricevuto un errore "La mappatura dell'interfaccia membro ..... non è supportato", che ho risolto in base a this thread. Per dimostrare:Differenza tra == e .Equals() con interfacce e LINQ

public interface IMyInterface { string valueText { get; set; } } 
public class MyData : IMyInterface 
{ 
    int ID { get; set;} 
    string valueText { get; set;} 
} 
public class MyOtherData : IMyInterface 
{ 
    long ID { get; set;} 
    string valueText { get; set;} 
} 

e

public static IEnumerable<T> GetByValue<T>(string value) : where T : class, IMyInterface, new() 
{ 
    using (var context = new DataContext()) 
    { 
     // The important line 
     return context.GetTable<T>().Where(x => x.valueText == value); 
    } 
} 

L'esecuzione di questo codice, mi piacerebbe avere un NotSupportedException: "La mappatura del membro di interfaccia IMyInterface.valueText non è supportato". Tuttavia, se sostituisco lo x.valueText == value con x.valueText.Equals(value), tutto funziona come previsto.

Ho risolto questo nel mio codice, ma voglio capire perché si comporta in questo modo. Qualcuno può spiegarlo?

Aggiornamento: Come per il mio commento qui sotto, il team LINQ to SQL ha chiuso questo come un "Non risolverà". Penso che ciò significhi che ora conta come un bug noto, ma che non sarà risolto in tempi brevi. Mi piacerebbe comunque sapere perché si comporta diversamente in primo luogo, però.

+0

Dopo aver letto il thread a cui ti sei collegato, direi che questo sembra un bug. – phoog

+0

@phoog, direi anche un errore, tranne che c'è un errore esplicito. Ciò significa che qualcosa deve essere verificato per quello scenario. Potrebbe trattarsi di un tipo di bug "dimenticato di aggiungere la logica" o di un'eccezione codificata per evitare un bug, ma di per sé, penso che l'eccezione sia il comportamento "corretto". – Bobson

+0

@ Bobson, hai controllato la connessione per vedere se qualcuno ha mai segnalato il bug? Un paio di persone nel thread collegato ne hanno parlato, ma sembra che nessuno abbia avuto abbastanza iniziative per farlo da solo. – phoog

risposta

2

Apparentemente la decisione di inviare la query a monte del server è basata su un insieme di regole incomplete, quindi LINQ-to-SQL trova un costrutto (un'interfaccia) che non può gestire.

La chiamata al metodo non è supportata da LINQ-to-SQL, quindi genera una query per recuperare tutti i record e quindi utilizza LINQ-to-Objects per filtrarli. (In realtà, in base al tuo altro thread, LINQ-to-SQL può fare un'eccezione speciale per object.Equals e sa come convertirlo in SQL).

LINQ-to-SQL probabilmente dovrebbe ricadere sul comportamento LINQ-to-Objects quando un'interfaccia è coinvolta, ma a quanto pare si limita a generare un'eccezione.

+1

Oh preferisco di gran lunga l'eccezione. Scoprire che stava scaricando il contenuto della tabella per filtrare in memoria probabilmente mi avrebbe fatto perdere la programmazione e unirmi al circo. –

+0

Se si deve credere alla risposta accettata sul thread collegato, la tua congettura è errata. Sembra che Linq to SQL generi un SQL corretto identico (inclusa una clausola 'WHERE' per il filtro) sia per il confronto' == 'che per la chiamata' .Equals', ma genera comunque un'eccezione per il confronto '=='. – phoog

+0

@ Ben, ma perché si comporta in modo diverso tra '==' e '.Equals()'? Per quanto ne so, sono la stessa cosa dietro le quinte e, come sottolinea @phoog, generano lo stesso SQL. – Bobson