views:

956

answers:

1

Good Morning!

Given:

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

This will compile, but on runtime I will get an Linq to Entity could not translate Comparer-Exception.
Any suggestions?

+8  A: 

If you're providing your own comparisons, you'll need to execute the Distinct call in .NET code. To make sure that happens, use AsEnumerable to turn IQueryable<T> into IEnumerable<T>:

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

Of course at that point you'll be pulling more data across from the database. An alternative is to group the data instead:

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

That will get you the first entity encountered with each ID (assuming my query-fu isn't failing me). That's basically what Distinct does anyway, but it's all at the database.

(Note to future readers: calling First() makes more sense than FirstOrDefault(), but apparently that doesn't work.)

Jon Skeet
Is there any chance to do this not in the .NET-Layer? Somehow tell the EF-call to do this in SQL?
Andreas Niedermair
See my edit - use grouping and you'll get the desired behaviour. It would be nice to have "DistinctBy" in the framework (and handled by EF etc) but I think the grouped version will do what you want.
Jon Skeet
Thank you! This looks very plausible to me, as you are doing the group on an IQueryable<T>. I will try this later on! PS.: Yes, you got the Distinct-Condition correct :)
Andreas Niedermair
System.NotSupportedException: The method 'First' can only be used as a final query operation. Consider using the method 'FirstOrDefault' in this instance instead.
Andreas Niedermair
Rats. Did you try using FirstOrDefault? If that works, I'll fix my answer :)
Jon Skeet
Yes ... with FirstOrDefault everything works :)
Andreas Niedermair
Cool - will edit.
Jon Skeet