2013-06-20 4 views
0

Я новичок в Entity Framework и присоединился к проекту, который использует общий репозиторий, как показано ниже. Существуют ли какие-либо недостатки в способе создания репозитория? Я заметил, что в большинстве руководств описывается создание нескольких репозиториев на основе общего базового репозитория, а не наличие одного универсального репозитория, который обрабатывает все.Entity Framework 4.1 Общий репозиторий установлен

Чтобы предоставить некоторый фон, этот код является частью веб-сайта ASP.NET MVC 3, и мы используем единство как контейнер МОК. Все компоненты бизнес-уровня наследуются от базового класса, который имеет IEntityRepository, введенный через конструктор.

Это универсальный класс Repository

public class MyRepository 
{ 
    private const string containerName = "myEntities"; 
    private readonly ObjectContext context; 
    private readonly Hashtable objectSets; 

    // Track whether Dispose has been called. 
    private bool disposed; 

    public MyRepository() 
    { 
     string connectionString = ConfigurationManager.ConnectionStrings[containerName].ConnectionString; 

     context = new ObjectContext(connectionString) {DefaultContainerName = containerName}; 
     context.ContextOptions.LazyLoadingEnabled = true; 
     context.ContextOptions.ProxyCreationEnabled = true; 

     objectSets = new Hashtable(); 
    } 

    private ObjectSet<TEntity> GetObjectSet<TEntity>() where TEntity : class 
    { 
     ObjectSet<TEntity> objectSet; 

     var type = typeof (TEntity); 
     if (objectSets.ContainsKey(type)) 
     { 
      objectSet = objectSets[type] as ObjectSet<TEntity>; 
     } 
     else 
     { 
      objectSet = context.CreateObjectSet<TEntity>(); 
      objectSets.Add(type, objectSet); 
     } 

     return objectSet; 
    } 

    public IQueryable<TEntity> GetAll<TEntity>(params string[] entities) where TEntity : class 
    { 
     ObjectQuery<TEntity> objectQuery = GetObjectSet<TEntity>(); 

     foreach (var entity in entities) 
     { 
      objectQuery = objectQuery.Include(entity); 
     } 

     return objectQuery; 
    } 


    public void Insert<TEntity>(TEntity entity) where TEntity : class 
    { 
     ObjectSet<TEntity> objectSet = GetObjectSet<TEntity>(); 
     objectSet.AddObject(entity); 
    } 

    public void Update<TEntity>(TEntity entity) where TEntity : class 
    { 
     ObjectSet<TEntity> objectSet = GetObjectSet<TEntity>(); 

     EntityKey key = objectSet.Context.CreateEntityKey(objectSet.EntitySet.Name, entity); 

     object originalItem; 
     if (objectSet.Context.TryGetObjectByKey(key, out originalItem)) 
     { 
      objectSet.ApplyCurrentValues(entity); 
     } 
     else 
     { 
      objectSet.Attach(entity); 
      objectSet.ApplyCurrentValues(entity); 
     } 
    } 

    public void Delete<TEntity>(TEntity entity) where TEntity : class 
    { 
     ObjectSet<TEntity> objectSet = GetObjectSet<TEntity>(); 
     objectSet.DeleteObject(entity); 
    } 

    public void SaveChanges() 
    { 
     try 
     { 
      context.SaveChanges(); 
     } 
     catch (Exception ex) 
     { 
      ex.ToString(); 
      throw ex; 
     } 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
     // Take yourself off the Finalization queue 
     // to prevent finalization code for this object 
     // from executing a second time. 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     // Check to see if Dispose has already been called 
     if (!disposed) 
     { 
      if (disposing) 
      { 
       context.Dispose(); 
      } 
     } 
     disposed = true; 
    } 

    ~MyRepository() 
    { 
     Dispose(false); 
    } 
} 

Это интерфейс, используемый, чтобы выставить методы:

public interface IEntityRepository : IDisposable 
{ 
    void Delete<TEntity>(TEntity entity) where TEntity : class; 

    IQueryable<TEntity> GetAll<TEntity>(params string[] entities) where TEntity : class; 

    void Insert<TEntity>(TEntity entity) where TEntity : class; 

    void Update<TEntity>(TEntity entity) where TEntity : class; 

    void SaveChanges(); 
} 

ответ

1

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

Имея все ваши репозитории, наследуемые от базового хранилища, вы можете создавать такие методы, как: GetProductsInsSock() или такие вещи, как UpdateOnlyProductsThatSatisfySomething().

Но возможны некоторые обходные пути! ;-)

Продолжайте использовать свой общий репозиторий, если он подходит вашей команде, единственное, что вам нужно добавить, это метод, который принимает параметр Specification. Как Эрик Эванс и Мартин Фаулер сказал:

Основная идея спецификации, чтобы отделить заявление о том, как в соответствии с кандидатом, от объекта-кандидата, что он соответствует против.

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

Вы можете просто добавить это к вашему IRepository интерфейса:

IEnumerable<T> Find(Specification<T> predicate); 

Реализация метода в вашем Repository класса будет выглядеть так:

public class Repository<T> : IRepository<T> where T : class 
{ 
    public Repository(IDbContext context) 
    { 
    _context = context; 
    _dbset = context.Set<T>(); 
    } 

    // some code... 

    public IEnumerable<T> Find(Specification<T> specification) 
    { 
    return _dbset.Where(specification.Predicate); 
    } 

    // some code... 
} 

Specification класс может выглядеть следующим образом:

public class Specification<T> 
{ 
    public Specification(Expression<System.Func<T, bool>> predicate) 
    { 
    _predicate = predicate; 
    } 

    internal Expression<System.Func<T, bool>> Predicate 
    { 
    get { return _predicate; } 
    } 

    private readonly Expression<System.Func<T, bool>> _predicate; 
} 

Пример из вызова:

var specification = ProductSpecification.InStock(); 
var product = Repository.Find(specification).FirstOrDefault(); 

И, наконец, ProductSpecification класс:

internal static class ActionSpecification 
{ 
    internal static Specification<Product> InStock() 
    { 
    return new Specification<Product>(p => p.IsInStock == true); 
    } 
}