Ошибка EF Distinct (IEqualityComparer) - PullRequest
14 голосов
/ 18 июня 2009

Доброе утро!

Дано:

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

Это скомпилируется, но во время выполнения я получу Linq to Entity could not translate Comparer -Exception.
Есть предложения?

1 Ответ

31 голосов
/ 18 июня 2009

Если вы предоставляете свои собственные сравнения, вам нужно выполнить вызов Distinct в .NET-коде. Чтобы это произошло, используйте AsEnumerable, чтобы превратить IQueryable<T> в IEnumerable<T>:

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

Конечно, в этот момент вы будете извлекать больше данных из базы данных. Альтернативой является группировка данных:

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

Это даст вам первую сущность, обнаруженную с каждым идентификатором (при условии, что мой запрос-фу меня не подводит). Это в основном то, что Distinct делает в любом случае, но это все в базе данных.

(Примечание для будущих читателей: звонить по номеру First() имеет больше смысла, чем FirstOrDefault(), но, очевидно, это не работает.)

...