2017-02-21 32 views
0

Ошибка: Невозможно создать постоянное значение типа «System.Object». В этом контексте поддерживаются только примитивные типы или типы перечислений.Выражение Linq не допускает Generic Тип свойства

Ok здесь дело, У меня есть Generic Base Entity, как показано ниже:

public abstract class Entity<Tkey> : IEntity<Tkey> 
    where Tkey:IComparable 
{ 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public abstract Tkey Id { get; set;} 

} 

Я предпочитаю это, потому что вы знаете, тип столбца идентификации некоторой таблицы является Guid, некоторые INT и некоторые длинный.

Таким образом, в моем Generic хранилище у меня есть какой-то способ, как этот один: метод

public class FRepository<TEntity,Tkey>:IDisposable where TEntity : Entity<Tkey>, new() 
    where Tkey:IComparable 

{ 

    public TEntity Find(Tkey id) 
    { 
     return this.GetAll().Where(e=> e.Id.CompareTo(id)==0).FirstOrDefault(); 
    } 
} 

GETALL() возвращает IQueryable<TEntity>.

Но когда я использую Linq, чтобы найти конкретный объект, он бросает исключение, как я напишите начало этого сообщения.

Примечание: Лицо, которое я пытаюсь найти Id есть с целого типа, так что это примитивный тип ...

Примечание-1: Я не могу в состоянии использовать «==» оператора с общий тип TKey. Я получаю ошибку компиляции.

Note-2: Я также пробовал это Where(e=>e.Id.GetHashCode()==id.GetHashCode()). Это вызывает еще одну ошибку (время выполнения).

LINQ to Entities не распознает метод 'Int32 GetHashCode()', и этот метод не может быть переведен в выражение хранилища.

+0

Я достиг этого, добавив метод Where в общий репозиторий, который позволяет использовать предикат.И затем я нажимаю предикат на один уровень вниз, как 'return GetAll(). Где (предикат) .FirstOrDefault();' –

+5

BTW, почему 'IComparable '? Не лучше 'IEquatable ' для 'Id' равенство? –

+1

Какую ошибку компиляции вы используете с 'e.Id == id'? –

ответ

2

Вместо того чтобы попытаться решить исходную проблему, так как некоторые другие пользователи уже комментировал, что не все допустимые выражения переводимые в SQL под капюшонами, я постараюсь дать вам несколько советов ...

Резюме:

  • Вы хотите IdIEquatable<TId> реализовать, не IComparable<TId>. Таким образом, вы сможете написать типизированные равенства следующим образом: id.Equals(id2). BTW EF не может обрабатывать IEquatable<T>.Equals либо (см. Is it possible to use IComparable to compare entities in Entity Framework?). В любом случае, вы больше не собираетесь идти по этому маршруту, но совет по-прежнему действителен, вы хотите IEquatable<T>, а не сравнение. См. Следующий пункт, чтобы узнать, почему.
  • Вы не хотите использовать метод GetAll в своих хранилищах позже искать объект по Id. Для этого точного варианта использования Entity Framework уже имеет IDbSet<T>.Find method.

Кроме того, я хотел бы призвать вас читать какой-то ответ я написал в 2011 году (уже давно) против GetAll в хранилищах: Repository design pattern. Кроме того, я документировал шаблон репозитория here, где я объясняю вещь против GetAll.