2009-06-18 16 views
14

¡Buenos días!EF Distinct (IEqualityComparer) Error

dado:

public class FooClass 
{ 
    public void FooMethod() 
    { 
     using (var myEntity = new MyEntity) 
     { 
      var result = myEntity.MyDomainEntity.Where(myDomainEntity => myDomainEntity.MySpecialID > default(int)).Distinct(new FooComparer); 
     } 
    } 

} 

public class FooComparer : IEqualityComparer<MyEntity.MyDomainEntity> 
{ 
    public bool Equals(MyEntity.MyDomainEntity x, MyEntity.MyDomainEntity y) 
    { 
     return x.MySpecialID == y.MySpecialID; 
    } 

    public int GetHashCode(MyEntity.MyDomainEntity obj) 
    { 
     return obj.MySpecialID.GetHashCode(); 
    } 
} 

Esto compilará, pero en tiempo de ejecución que recibirá Linq to Entity could not translate Comparer -Exception.
¿Alguna sugerencia?

Respuesta

29

Si está proporcionando sus propias comparaciones, deberá ejecutar la llamada Distinct en código .NET. Para asegurarse de que sucede, utilice AsEnumerable convertir IQueryable<T> en IEnumerable<T>:

var result = myEntity.MyDomainEntity 
     .Where(myDomainEntity => myDomainEntity.MySpecialID > default(int)) 
     .AsEnumerable() 
     .Distinct(new FooComparer()); 

Por supuesto que en ese momento se le tira más datos a través de la base de datos. Una alternativa consiste en agrupar los datos en su lugar:

var result = from entity in myEntity.MyDomainEntity 
      where entity.MySpecialID > 0 
      group entity by entity.MySpecialID into groups 
      select groups.FirstOrDefault(); 

que les permite conocer la primera entidad encontrado con cada ID (asumiendo mi consulta-fu no me está fallando). Eso es básicamente lo que hace Distinct de todos modos, pero todo está en la base de datos.

(Nota para los futuros lectores: llamar First() tiene más sentido que FirstOrDefault(), pero al parecer eso no funciona.)

+0

¿Hay alguna posibilidad de hacerlo no en el .NET-Capa? ¿De alguna manera le dicen a EF-call que haga esto en SQL? –

+0

Ver mi edición - use la agrupación y obtendrá el comportamiento deseado. Sería bueno tener "DistinctBy" en el marco (y manejado por EF, etc.) pero creo que la versión agrupada hará lo que usted desee. –

+0

¡Gracias! Esto parece muy plausible para mí, ya que está haciendo el grupo en un IQueryable . ¡Intentaré esto más adelante! PD: Sí, tiene la Distinct-Condition correcta :) –