Если я правильно понимаю этот метод, он возвращает одну запись для любого типа T на основе первичного ключа.
У нас также есть общий репозиторий, но интерфейс выглядит так:
public interface IRepository<T> where T : class
{
void Add(T entity);
void Remove(T entity);
void Attach(T entity);
IQueryable<T> Find();
}
И наша общая реализация репозитория:
public class GenericRepository<T> : IRepository<T> where T : class
{
public IQueryable<T> Find()
{
return _ctx.GetEntitySet<T>(); // EF plularization/reflection smarts
}
}
Итак, чтобы получить эквивалентную одиночную запись для «Поста»:
var postId = 1;
IRepository<Post> repository = new GenericRepository<Post>(); // done by DI in reality
repository
.Find()
.SingleOrDefault(x => x.PostId == postId); // explicit predicate to grab record
Это сильно отличается от вашего исходного кода - так как вызывающий код определяет первичный ключ (или способ идентификации уникальной записи).
Честно говоря, пытаться динамически получить уникальную запись, основанную на постоянном значении первичного ключа, довольно безумно - что, если это составной ключ? Я не вижу, как этот код будет работать.
Рад видеть другие ответы, но я бы сказал проще.
Если вы хотите, чтобы код захватывал набор сущностей, основанный на T, я могу поделиться этим - но это довольно просто.
Если вы хотите, чтобы метод захватил одну запись, позвольте вызывающему коду предоставить предикат / ключ:
public T FindSingle(Expression<Func<T,bool>> predicate)
{
return _ctx.GetEntitySet<T>.SingleOrDefault(predicate);
}
Тогда, если, например, «Post» имеет составной ключ «PostName» и «PostType»:
var singlePost = repository.FindSingle(post => post.PostName == "Foo" && post.PostType == "Question");
В вашем примере ваш репозиторий диктует вашу модель, заставляя каждую сущность иметь первичный ключ из одного столбца.
Ваш репозиторий должен помочь вашей модели, а не определять ее.
EDIT - код для GetEntitySet<T>
, по запросу
public IObjectSet<T> GetEntitySet<T>() where T : class
{
var entityName = _plularizer.Pluralize(typeof(T).Name);
string entitySetName = string.Format("{0}.{1}", EntityContainerName, entityName);
return CreateObjectSet<T>(entitySetName );
}
Довольно просто и довольно безопасно, потому что _plularizer
имеет тип System.Data.Entity.Design.PluralizationService
, который является тем же модулем, который EF использует для создания имен наборов сущностей по умолчанию.
EntityContainerName
- имя вашего контейнера для ваших сущностей.
Ваш экземпляр _plularizer
должен быть статическим и должен быть защищен от потоков с полностью заблокированным синглтоном.
НТН.