我是Entity Framework的新手,加入了一个使用通用存储库的项目,如下所示。存储库的设置方式是否有任何缺点?我注意到大多数教程都描述了基于通用基础存储库创建多个存储库,而不是拥有一个处理所有内容的通用存储库。
为了给出一些背景知识,这段代码是ASP.NET MVC 3网站的一部分,我们使用unity作为IOC容器。业务层中的所有组件都继承自通过构造函数注入IEntityRepository的基类。
这是通用存储库类
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();
}
答案 0 :(得分:1)
使用通用存储库而不是每个Aggregate root具有一个具体的存储库实现的主要缺点是,您无法为特定用法创建特定方法。
让所有存储库从基础存储库继承后,您可以创建类似:GetProductsInsSock()
或类似UpdateOnlyProductsThatSatisfySomething()
的方法。
但是有一些解决方法可用! ; - )
继续使用您的通用存储库(如果它适合您的团队),您可能必须添加的唯一方法是接受Specification
作为参数的方法。正如Eric Evans和Martin Fowler所说:
规范的核心思想是分离如何陈述 从候选对象匹配候选对象 对
在您的情况下,它可以作为过滤器来检索正确的实体,而无需创建特定的方法。
您只需将其添加到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);
}
}