2012-04-11 16 views
11

Recientemente recibí un error "El mapeo de la interfaz ..... no es compatible", que resolví basándome en this thread. Para demostrar:Diferencia entre == y .Equals() con interfaces y 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;} 
} 

y

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); 
    } 
} 

La ejecución de este código, me gustaría obtener un NotSupportedException: "El mapeo de miembro de interfaz IMyInterface.valueText no es compatible". Sin embargo, si reemplazo el x.valueText == value con x.valueText.Equals(value), esto funciona del todo como se esperaba.

He resuelto esto en mi código, pero quiero entender por qué se comporta de esta manera. ¿Alguien puede explicarlo?

Actualización: Según mi comentario a continuación, el equipo de LINQ to SQL cerró esto como "No se corregirá". Creo que eso significa que ahora cuenta como un error conocido, pero que no se resolverá en el corto plazo. Sin embargo, me gustaría saber por qué se comporta de manera diferente en primer lugar.

+0

Después de leer el hilo que enlazó, diría que esto parece un error. – phoog

+0

@phoog, asumiría un error también, excepto que hay un error explícito para ello. Lo que significa que algo tiene que verificar ese escenario. Podría ser un tipo de error "se olvidó de agregar la lógica" o una excepción codificada para evitar un error, pero en sí mismo, creo que la excepción es el comportamiento "correcto". – Bobson

+0

@ Bobson, ¿se ha conectado para ver si alguien ha denunciado el error? Un par de personas en el hilo vinculado hablaron sobre eso, pero parece que nadie tuvo suficiente iniciativa para hacerlo por sí mismo. – phoog

Respuesta

2

Aparentemente, la decisión de enviar la consulta en sentido ascendente al servidor se basa en un conjunto incompleto de reglas, y luego LINQ-to-SQL encuentra un constructo (una interfaz) que no puede tratar.

La llamada al método no es compatible con LINQ-to-SQL, por lo que genera una consulta para recuperar todos los registros y luego utiliza LINQ-to-Objects para filtrarlos. (En realidad, según su otro hilo, LINQ-to-SQL puede hacer una excepción especial para object.Equals y sabe cómo convertir eso a SQL).

LINQ-to-SQL probablemente debería recurrir al comportamiento LINQ-to-Objects cuando se trata de una interfaz, pero aparentemente solo arroja una excepción.

+1

Oh, yo prefiero la excepción. Descubrir que estaba descargando el contenido de la tabla para filtrar en la memoria probablemente me haría abandonar la programación y unirme al circo. –

+0

Si se debe creer la respuesta aceptada en el hilo enlazado, su conjetura es incorrecta. Parece que Linq a SQL genera SQL correcto idéntico (incluyendo una cláusula 'WHERE' para el filtro) para la comparación' == 'y la llamada' .Equals', pero arroja una excepción para la comparación '=='. – phoog

+0

@Ben, pero ¿por qué se comporta de manera diferente entre '==' y '.Equals()'? Hasta donde yo sé, son lo mismo detrás de las escenas, y como señala @phoog, generan el mismo SQL. – Bobson

Cuestiones relacionadas