Как да внедрим общ метод GetById с помощта на Entity Framework 4 и модела на хранилището?

Имам общо хранилище и бих искал да внедря общ метод GetById. Това е интерфейсът на моето хранилище досега:

public interface IRepository<T> where T : EntityObject  
{
    void Add(T entity);
    void Delete(int id);
    void Delete(T entity);
    IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
    T SingleOrDefault(Expression<Func<T, bool>> predicate);
    IEnumerable<T> GetAll();
    T GetById(int id);
    void Save();
    T Single(Expression<Func<T, bool>> predicate);
}

Използвам Entity Framework 4.1. Много от решенията, които открих, използваха абстрактен базов клас интерфейс за клас IEntity, от който обектите трябва да наследят, за да извършат търсенето на Id.

Вместо да се налага да прилагам интерфейс за всичките си класове, аз се опитвах да използвам този код:

T entity = _objectSet.Where(
    x => x.EntityKey.EntityKeyValues
          .Select(v => v.Value.Equals(id)).Count() == 1).First();

Въпреки това, когато се опитвам да използвам метода, получавам изключение:

The specified type member 'EntityKey' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

Може ли някой да ми каже как мога да накарам това да работи?

Актуализация 1

Членовете _objectContext и _context се декларират така:

private readonly ObjectContext _context;
private readonly IObjectSet<T> _objectSet;

Благодаря.


person b3n    schedule 03.04.2011    source източник
comment
Проверете този отговор: stackoverflow.com/questions/5273416/ Съдържа точно това, което търсите.   -  person Ladislav Mrnka    schedule 03.04.2011


Отговори (2)


От този въпрос Как да получа името на ключа за обект на ObjectSet‹T›?, можете да мамите малко и да използвате ESQL.

    public T GetById(int id)
    {

        var keyPropertyName = _objectSet.EntitySet.ElementType.KeyMembers[0].ToString();        

        T entity = _objectSet.Where("it." + keyPropertyName + "=" + id).First();
        return entity;

    }

Включих целия необходим код в метода, очевидно искате да го преработите малко, но трябва да работи за вас.

person Rob    schedule 03.04.2011
comment
Добавих малко информация по-горе, тъй като моят ObjectSet не излага свойство Context или EntitySet. - person b3n; 03.04.2011
comment
Няма значение, промяната на IObjectSet на ObjectSet свърши работа. Ще публикувам, ако работи по-късно. - person b3n; 03.04.2011
comment
Какво да кажем, ако не знаем точно типа данни за id. Може да е int, Int16, Int64, long и т.н. Какъв би бил най-добрият подход за динамично прехвърляне към типа данни Id на обекта? - person razp26; 11.09.2015
comment
Ние наистина го използваме само като низ тук, така че можете да промените типа id на каквото и да е, стига методът ToString() да отразява точно стойността, трябва да сте в добра форма. - person Rob; 12.11.2015

За тези, които имат достатъчно късмет да работят във VB.net и вие се борите да получите работещ пример:

Imports System.Runtime.CompilerServices
Imports System.Data.Objects
Imports System.Collections.Generic

Public Module ObjectSetExtension

    <Extension()>
    Public Function GetById(Of T As Class)(self As ObjectSet(Of T), Id As Integer)
        Dim keyPropertyName = self.EntitySet.ElementType.KeyMembers(0).ToString()
        Dim entity As T = self.Where("it." & keyPropertyName & "=" & Id).First
        Return entity
    End Function

    <Extension()>
    Public Function GetById(Of T As Class)(self As ObjectSet(Of T), Id As Guid)
        Dim keyPropertyName = self.EntitySet.ElementType.KeyMembers(0).ToString()
        ' 'note the "GUID" in the string. DO NOT REMOVE!
        Dim entity As T = self.Where("it." & keyPropertyName & "=GUID '" & Id.ToString() & "'").First
        Return entity
    End Function

End Module
person Atron Seige    schedule 19.02.2014