2013-11-07 6 views
0

Я работаю над ASP.NET MVC 4 проектом с нуля. Я решил начать с уровня доступа к данным, используя Entity Framework 5 и Code First рабочий процесс. Компания, с которой я работал, использовала очень хорошую реализацию (по-моему) Repository pattern, включая репозитории, службы, абстрактную фабрику для хранилищ и услуг и Unity для DI. Я попытался его переделать, но это слишком сложно для меня и будет стоить мне много времени, чтобы воспроизвести то, что я там использовал, поэтому я решил провести некоторое исследование и пойти с чем-то более легким.GenericRepository и настройка UnitOfWork

Поэтому я решил использовать GenericRepository и UnitOfWork - вдали от первоначального плана, но это была реализация, которая показывалась в большинстве моих поисков. Поэтому я сделал очень базовую реализацию (до такой степени, что я уверен, что знаю, что происходит, может быть, даже ниже моих способностей, чтобы понять), и на самом деле я думаю, что для этого точного проекта это может быть достаточно, но я хочу, чтобы иметь возможность вызывать дополнительные пользовательские методы для разных объектов.

Я думаю, что это сильно зависит от идеи общего репозитория, но если я попытаюсь пойти с какой-то другой реализацией, она будет экспоненциально сложнее, поэтому я задаюсь вопросом, есть ли способ добавить это в мою реализацию, не причиняя слишком большого вреда идея общего репозитория.

То, что я в настоящее время является GenericRepository класс:

public class GenericRepository<TEntity> where TEntity : class 
    { 
     internal DBContext context; 
     internal DbSet<TEntity> dbSet; 

     public GenericRepository(DBContext context) 
     { 
      this.context = context; 
      this.dbSet = context.Set<TEntity>(); 
     } 

     public virtual IEnumerable<TEntity> Get() 
     { 
      IQueryable<TEntity> query = dbSet; 
      return query.ToList(); 
     } 
     //just the standard implementation 

и мой UnitOfWork класс:

public class UnitOfWork : IDisposable 
    { 
     private DBContext context = new DBContext(); 
     private CustomerRepository customerRepository; 

     public CustomerRepository CustomerRepository 
     { 
      get 
      { 
       if (this.customerRepository == null) 
        this.customerRepository = new CustomerRepository(context); 
       return customerRepository; 
      } 
     } 

     private GenericRepository<Order> orderRepository; 

     public GenericRepository<Order> orderRepository 
     { 
      get 
      { 

Так как вы можете видеть, что мой Order объект с помощью GenericRepository, но я сделал тестовый класс CustomerRepository для моего Customer объекта.

Сейчас этот класс CustomerRepository выглядит следующим образом:

public class CustomerRepository : GenericRepository<Customer> 
    { 
     public CustomerRepository(DBContext context) : base(context) { } 
    } 

и идея заключается в том, чтобы добавить методы, которые явно для Customer сущности здесь. Я не уверен, что это правильно, особенно так, как я называю конструктор. Однако каков естественный способ добавления этих конкретных методов для разных объектов? Я не против даже сделать шаг назад, чтобы реализовать его лучше, но я не хочу бросать его, потому что я пытался, и в настоящий момент вся концепция слишком сложна для меня, и я хочу быть уверенным, что я понимаю вещи что я использую в своем коде.

+0

Вы должны посмотреть http://hwyfwk.com/Highway.Data/index.html – Kit

ответ

1

Я думаю, что вы на правильном пути. Вот общий репозиторий, который я использую:

public interface IRepository<TEntity> 
    where TEntity : class 
{ 
    IQueryable<TEntity> GetAll(); 
    IQueryable<TEntity> GetBy(Expression<Func<TEntity, bool>> predicate); 
    TEntity GetById(long id); 
    void Add(TEntity entity); 
    void Update(TEntity entity); 
    void Delete(TEntity entity); 
} 

public class Repository<TEntity> : IRepository<TEntity> 
    where TEntity : class 
{ 
    protected readonly DbEntities Context; 
    protected readonly DbSet<TEntity> Set; 

    public Repository() 
    { 
     Context = new DbEntities(); 
     Set = Context.Set<TEntity>(); 
    } 

    public virtual IQueryable<TEntity> GetAll() 
    { 
     return Set; 
    } 

    public virtual IQueryable<TEntity> GetBy(Expression<Func<TEntity, bool>> predicate) 
    { 
     return Set.Where(predicate); 
    } 

    public virtual TEntity GetById(long id) 
    { 
     return Set.Find(id); 
    } 

    public virtual void Add(TEntity entity) 
    { 
     Set.Add(entity); 
     Context.SaveChanges(); 
    } 

    public virtual void Update(TEntity entity) 
    { 
     Set.Attach(entity); 
     Context.Entry(entity).State = EntityState.Modified; 
     Context.SaveChanges(); 
    } 

    public virtual void Delete(TEntity entity) 
    { 
     Set.Remove(entity); 
     Context.SaveChanges(); 
    } 
} 


// And assuming User is a data object with an Id property: 
public interface IUserSpecificRepository 
{ 
    List<User> GetById(long id) 
} 

public class UserSpecificRepository : IUserSpecificRepository, Repository<User> 
{ 
    public virtual List<User> GetById(long id) 
    { 
     return GetBy(x => x.Id = id).ToList(); 
    } 
} 

Обратите внимание, что GetAll() и GetBy() возвращают запрашиваемый. Это позволяет контролировать, когда выражение запроса преобразуется в SQL и попадает в базу данных. Обычно это вызовет ToList(). Затем вы можете наследовать это, и любые пользовательские методы могут использовать эти два стартовых метода.

Также, как правило, вы никогда не должны делать GetAll().ToList(), как сейчас. Если у вас есть записи zilion, у вас возникнут проблемы. Это также проблема производительности, если вы фильтруете до нескольких записей. GetAll().ToList().Where(x => x.Id = 1) в основном получает все zillion записи из db в память, а затем фильтрует его до одного. Вы должны сделать это GetAll().Where(x => x.Id = 1).ToList().

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

+0

Обратите внимание, что DbEntities является EF DBContext. – Jaguir

+0

Итак, если вы хотите добавить дополнительные методы для какой-либо сущности, что вы делаете? Создайте интерфейс, например, например: «IUserRepository: IRepository », а затем создайте класс - «UserRepository: репозиторий , IUserRepository'? Не могли бы вы добавить пример того, как вы расширяете эту архитектуру в этом контексте? – Leron

+0

Я добавил в пример «UserSpecificRepository». Он имеет только один метод, но должен предоставить скелет для любых типизированных репозиториев, которые вы хотите создать. – Jaguir

Смежные вопросы