2009-06-18 30 views
14

Buongiorno!Errore EF Distinct (IEqualityComparer)

Dato:

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

Questo compilerà, ma il tempo di esecuzione mi metterò un Linq to Entity could not translate Comparer -Exception.
Qualche suggerimento?

risposta

29

Se si forniscono i propri confronti, è necessario eseguire la chiamata Distinct nel codice .NET. Per assicurarsi che accade, utilizzare AsEnumerable per trasformare IQueryable<T> in IEnumerable<T>:

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

Naturalmente a quel punto ti verrà tirando più dati di fronte al database. Un'alternativa è quella di raggruppare i dati, invece:

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

che ti porterà la prima entità incontrate con ogni ID (supponendo la mia domanda-fu non mi sta venendo a mancare). Questo è fondamentalmente ciò che Distinct fa comunque, ma è tutto nel database.

(Nota per i lettori futuri: chiamando First() ha più senso di FirstOrDefault(), ma a quanto pare questo non funziona.)

+0

c'è qualche possibilità di farlo, non in .NET-layer? In qualche modo dire alla chiamata EF di fare questo in SQL? –

+0

Vedere la mia modifica: usa il raggruppamento e otterrai il comportamento desiderato. Sarebbe bello avere "DistinctBy" nel framework (e gestito da EF ecc.) Ma penso che la versione raggruppata farà quello che vuoi. –

+0

Grazie! Questo mi sembra molto plausibile, dato che stai facendo il gruppo su un IQueryable . Ci proverò più tardi! PS .: Sì, la condizione Distinct è corretta :) –