Реализация общего репозитория с EF - PullRequest
1 голос
/ 25 апреля 2011

Для простого репозитория

public interface ISimpleRepository<T>
{
    IApplicationState AppState { get; set; }
    void Add(T instance);
    void Delete(T instance);
    void Delete(Guid rowGuid);
    IQueryable<T> GetAll();
    T Load(Guid rowGuid);
    void SaveChanges();
    void Update(T instance);
}

Моя реализация метода Load() для конкретного хранилища для класса Product может выглядеть так:

    public Product Load(Guid rowid)
    {
        return (from c in _ctx.Products where c.id == rowid select c).FirstOrDefault();
    }

Теперь это предполагается, когда мой класс реализации репозитория выглядит так:

public class EntityFrameworkProductsProvider : IRepository<Product> ...

Что если бы у меня было несколько десятков или сотен этих маленьких и простых сущностей, которые все использовали бы одно и то же поведение при выполнении CRUD (используя одну и ту же реализацию методов)? Я, конечно, не хочу идти и создавать класс для реализации IRepository для каждого из них ..

Я хочу что-то вроде этого:

public class EntityFrameworkDefaultProvider<T> : IRepository<T> ...

но я не знаю, как реализовать выражение LINQ Select, потому что, конечно, я не могу написать from e in _ctx.T where e... или нет?

Я еще не сталкивался с этим сценарием, потому что до сих пор у меня были только очень специфические объекты с пользовательской реализацией репозитория.

Ответы [ 4 ]

4 голосов
/ 25 апреля 2011

Поскольку вы пометили свой вопрос с помощью и Я предполагаю, что вы используете ObjectContext API.ObjectContext предлагает метод CreateObjectSet<T>, который эквивалентен Set<T> для DbContext.

Этот вопрос на самом деле является дубликатом:

3 голосов
/ 25 апреля 2011

Вместо записи _ctx.Products вы можете написать _ctx.Set<T>. Это решает половину проблемы (вам нужно добавить общее ограничение where T: class в ваш репозиторий)

Затем, если rowid является ключом объекта, вы можете использовать _ctx.Set<T>.Find(rowid) вместо запроса LINQ для получения по идентификатору.

В качестве альтернативы, вы можете создать базовый интерфейс IHaveId (или класс BaseEntity, что хотите) со свойством Id, а затем добавить его в качестве общего ограничения для T, чтобы вы могли использовать его в ваших запросах.

2 голосов
/ 26 апреля 2011

Если вы используете EF 4.1, см. Образец общего репозитория здесь: http://www.asp.net/entity-framework/tutorials/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

1 голос
/ 25 апреля 2011

Я знаю, что это возможно в EF4.1 с API-интерфейсом DbContext, где у вас есть метод "Set" для контекста, который возвращает вам набор сущностей, соответствующий типу T. таким образом, вы можете иметь свой репозиторий какэто:

public class EntityFrameworkDefaultProvider<T> : IRepository<T> where T:class
{
    public T Load(Guid rowId)
    {
        return _context.Set<T>().Find(rowId);
    }
}

еще одно замечание: я думаю, вы могли бы использовать этот синтаксис:

return _ctx.Products.FirstOrDefault(c=>c.id == rowid);

, чтобы получить желаемую сущность вместо использования (from ... in ...).это понятнее (на мой взгляд):)

Надеюсь, это поможет

...