Подтвердить что ты не робот

Ошибка EF Distinct (IEqualityComparer)

Доброе утро!

Дано:

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.
Любые предложения?

4b9b3361

Ответ 1

Если вы предоставляете свои собственные сравнения, вам нужно выполнить вызов 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();

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

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