Pregunta

Tengo una entidad que me gustaría comparar con un subconjunto y determinar para seleccionar todos excepto el subconjunto.

Por lo tanto, mi consulta es similar al siguiente:

Products.Except(ProductsToRemove(), new ProductComparer())

El método devuelve un ProductsToRemove() List<Product> después de que se lleva a cabo una serie de tareas. Así que en su forma más simple es lo anterior.

Las miradas de clase ProductComparer() como esta:

public class ProductComparer : IEqualityComparer<Product>
{
    public bool Equals(Product a, Product b)
    {
        if (ReferenceEquals(a, b)) return true;

        if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
            return false;

        return a.Id == b.Id;
    }

    public int GetHashCode(Product product)
    {
        if (ReferenceEquals(product, null)) return 0;
        var hashProductId = product.Id.GetHashCode();
        return hashProductId;
    }
}

Sin embargo, continuamente recibir la siguiente excepción:

  

LINQ a Entidades no reconoce   el método   'System.Linq.IQueryable1[UnitedOne.Data.Sql.Product] Except[Product](System.Linq.IQueryable1 [UnitedOne.Data.Sql.Product],   System.Collections.Generic.IEnumerable1[UnitedOne.Data.Sql.Product], System.Collections.Generic.IEqualityComparer1 [UnitedOne.Data.Sql.Product])'   método, y este método no puede ser   traducido en una expresión tienda.

¿Fue útil?

Solución

LINQ a Entidades no es en realidad ejecuta la consulta, es Interpretación su código, convirtiéndola en TSQL, ejecutando luego de que en el servidor.

Debajo de las sábanas, se codifica con el conocimiento de cómo funcionan los operadores y funciones comunes y cómo se relacionan con los TSQL. El problema es que los desarrolladores de L2E tienen idea de cómo exactamente va a implementar IEqualityComparer. Por lo tanto no pueden darse cuenta de que cuando se dice == Clase A Clase B que quiere decir (por ejemplo) "¿Dónde Person.FirstName == == Person.LastName FirstName y Apellido".

Por lo tanto, cuando el intérprete L2E realiza un método que no reconoce, se lanza esta excepción.

Hay dos formas en las que puede evitar esto. En primer lugar, desarrollar un Donde () que satisfaga sus requisitos de igualdad, pero que no se basa en ningún método personalizado. En otras palabras, la prueba para la igualdad de las propiedades de la instancia en lugar de un método definido en la clase iguales.

En segundo lugar, se puede activar la ejecución de la consulta y luego hacer sus comparaciones en la memoria. Por ejemplo:

var notThisItem = new Item{Id = "HurrDurr"};
var items = Db.Items.ToArray(); // Sql query executed here
var except = items.Except(notThisItem); // performed in memory

Es evidente que esto traerá muchos más datos a través del cable y ser más intensivo de memoria. La primera opción suele ser la mejor.

Otros consejos

Usted está tratando de convertir la llamada Except con su IEqualityComparer personalizado en Entity SQL.

Obviamente, su clase no se puede convertir en SQL.

Debe Products.AsEnumerable().Except(ProductsToRemove(), new ProductComparer()) escritura para obligarlo a ejecutar en el cliente. Tenga en cuenta que esto va a descargar todos los productos desde el servidor.


Por cierto, la clase ProductComparer debe ser un producto único, de esta manera:

public class ProductComparer : IEqualityComparer<Product> {
    private ProductComparer() { }
    public static ProductComparer Instance = new ProductComparer();

    ...
}

El IEqualityComparer<T> sólo puede ser ejecutado a nivel local, no se puede traducir a un comando de SQL, por lo tanto, el error

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top