通用储存库与UnitOfWork与IoC自定义方法
本文关键字:IoC 自定义方法 UnitOfWork 储存库 | 更新日期: 2023-09-27 18:06:47
我有一个通用存储库模式与UnitOfWork,我正在使用IoC。除了存储库使用的基本方法之外,我还有一些自定义方法。我没有再次实现整个IRepository方法,而是继承了GenericRepository类。
这是我的UnitofWork实现:
public interface IUnitOfWork<T> : IDisposable where T : DbContext
{
int Save();
T Context { get; }
}
public class UnitOfWork<T> : IUnitOfWork<T> where T : MyContext, new()
{
private readonly T _context;
public UnitOfWork()
{
_context = new T();
}
public UnitOfWork(T Context)
{
_context = Context;
}
public int Save()
{
return _context.SaveChanges();
}
public T Context
{
get
{
return _context;
}
}
public void Dispose()
{
_context.Dispose();
}
}
我的仓库实现:
public interface IGenericRepository
{
IQueryable<T> All<T>() where T : class;
void Remove<T>(int id)where T : class;
void Remove<T>(T entity) where T : class;
void RemoveRange<T>(IList<T> entities) where T : class;
T Find<T>(int id) where T : class;
void Add<T>(T entity) where T : class;
void AddRange<T>(IList<T> entities) where T : class;
void Update<T>(T entity) where T : class;
int SaveChanges();
}
public class GenericRepository<C> : IGenericRepository where C : MyContext
{
protected readonly C _context;
public GenericRepository(IUnitOfWork<C> unitOfWork)
{
_context = unitOfWork.Context;
}
public int SaveChanges()
{
return _context.SaveChanges();
}
public IQueryable<T> All<T>() where T : class
{
return _context.Set<T>();
}
public void Remove<T>(int id) where T : class
{
T entity = _context.Set<T>().Find(id);
if (entity != null)
{
_context.Set<T>().Remove(entity);
}
}
public void Remove<T>(T entity) where T : class
{
if (entity != null)
{
_context.Set<T>().Remove(entity);
}
}
public void RemoveRange<T>(IList<T> entities) where T : class
{
if (entities.Count > 0)
{
_context.Set<T>().RemoveRange(entities);
}
}
public T Find<T>(int id) where T : class
{
return _context.Set<T>().Find(id);
}
public void Add<T>(T entity) where T : class
{
_context.Set<T>().Add(entity);
}
public void AddRange<T>(IList<T> entities) where T : class
{
_context.Set<T>().AddRange(entities);
}
public void Update<T>(T entity) where T : class
{
_context.Set<T>().Attach(entity);
_context.Entry(entity).State = System.Data.Entity.EntityState.Modified;
}
}
下面是一个Custom-Repository的例子:
public interface IUserAccountRepository : IGenericRepository
{
UserAccount Find(string email, string password);
bool CheckDuplicate(string email);
}
public class UserAccountRepository<C> : GenericRepository<C> where C : CSharpAssigmentContext, IUserAccountRepository
{
protected readonly C _context;
public UserAccountRepository(IUnitOfWork<C> unitOfWork)
{
_context = unitOfWork.Context;
}
public int SaveChanges()
{
return _context.SaveChanges();
}
/// <summary>
/// Find user by email and password
/// </summary>
public UserAccount Find(string email, string password)
{
return _context.Set<UserAccount>().Where(ua => ua.Email == email && ua.Password == password).FirstOrDefault(null);
}
/// <summary>
/// Check wether user exists or not
/// </summary>
public bool CheckDuplicate(string email)
{
return _context.Set<UserAccount>().Any(ua => ua.Email == email);
}
public IQueryable<T> All<T>() where T : class
{
return _context.Set<T>();
}
public void Remove<T>(int id) where T : class
{
T entity = _context.Set<T>().Find(id);
if (entity != null)
{
_context.Set<T>().Remove(entity);
}
}
public void Remove<T>(T entity) where T : class
{
if (entity != null)
{
_context.Set<T>().Remove(entity);
}
}
public void RemoveRange<T>(IList<T> entities) where T : class
{
if (entities.Count > 0)
{
_context.Set<T>().RemoveRange(entities);
}
}
public T Find<T>(int id) where T : class
{
return _context.Set<T>().Find(id);
}
public void Add<T>(T entity) where T : class
{
_context.Set<T>().Add(entity);
}
public void AddRange<T>(IList<T> entities) where T : class
{
_context.Set<T>().AddRange(entities);
}
public void Update<T>(T entity) where T : class
{
_context.Set<T>().Attach(entity);
_context.Entry(entity).State = System.Data.Entity.EntityState.Modified;
}
这是我的Unity IoC代码:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
//UnitOfWork and GenericRepository
container.RegisterType(typeof(IUnitOfWork<CSharpAssigmentContext>),typeof(UnitOfWork<CSharpAssigmentContext>), new HierarchicalLifetimeManager());
container.RegisterType(typeof(IGenericRepository), typeof(GenericRepository<CSharpAssigmentContext>), new HierarchicalLifetimeManager());
//I keep receiving compile ERROR here
container.RegisterType(typeof(IUserAccountRepository), typeof(UserAccountRepository<CSharpAssigmentContext>), new HierarchicalLifetimeManager());
//Services
container.RegisterType(typeof(IUsersAccountsService), typeof(UsersAccountsService), new TransientLifetimeManager());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
如代码中所述,我一直得到以下代码的编译时错误:
container.RegisterType(typeof(IUserAccountRepository), typeof(UserAccountRepository<CSharpAssigmentContext>), new HierarchicalLifetimeManager());
错误是:
类型MyContext不能用作泛型类型或方法中的类型参数C。没有隐含的从MyContext到IMyClassRepository的引用转换。
如何解决这个错误?对于自定义存储库,我的实现是否正确?
基金会错了。通用存储库应该有一个通用的实体参数。您的"通用"存储库确实具有具有通用参数T
的方法,但不能保证总是使用相同的实体。这个界面应该是这样的:
public interface IGenericRepository<TEntity> where TEntity : class
{
IQueryable<TEntity> All();
void Remove(int id);
void Remove(TEntity entity);
void RemoveRange(IList<TEntity> entities);
TEntity Find(int id);
void Add(TEntity entity);
void AddRange(IList<TEntity> entities);
void Update(TEntity entity);
int SaveChanges();
}
事实上,一旦您决定要在DbContext/DbSet
之上使用UoW/Repository层,我看不出有什么理由与这个标准示例不同。除了包含多个存储库的UoW之外,还可以看到一个类似的通用存储库。
这样做了,你所谓的"UserAccountRepository
",应该是一个服务,包含一个UoW,可以通过你的IoC容器注入:
public interface IUserAccountService // No repository!
{
UserAccount Find(string email, string password);
bool CheckDuplicate(string email);
}
示例实现:
public class UserAccountService : IUserAccountService
{
private readonly IUnitOfWork<CSharpAssigmentContext> _unitOfWork;
public UserAccountService(IUnitOfWork<CSharpAssigmentContext> unitOfWork)
{
this._unitOfWork = unitOfWork;
}
您可以看到,在这个UoW/Repository实现中,上下文没有公开。这就是这个抽象层的目的之一。
据我所知,您的UserAccountRepository
类定义可能存在错误:
public class UserAccountRepository<C> : GenericRepository<C>
where C : CSharpAssigmentContext, IUserAccountRepository
这个类定义可以这样读:
类型UserAccountRepository是一个泛型类型,泛型参数类型为C;useraccountrerepository继承自泛型类GenericRepository,其泛型参数为C类型;C类型必须继承CSharpAssignmentContext类,C类型必须实现iuseraccountrerepository接口。
将IUserAccountRepository
从泛型参数C
的类型约束中删除,并将其添加到GenericRepository后面的逗号后,应该可以完成工作:
public class UserAccountRepository<C> : GenericRepository<C>, IUserAccountRepository
where C : CSharpAssigmentContext
类定义现在可以读成这样:类型useraccountrerepository是泛型类型,其泛型参数为C类型;useraccountrerepository继承自泛型类GenericRepository,其泛型参数为C类型;type UserAccountRepository必须实现接口IUserAccountRepository。泛型参数类型(类型C)必须从类CSharpAssignmentContext继承。
当你从泛型类/接口和其他接口一起继承一个类时,你必须首先指定你继承或实现的类型,然后再指定泛型类型约束:
public class SomeImplementation<T1, T2> : ISomeInterface<T1>, IAnotherInterface<T2>, IDisposable, ICloneable
where T1 : IAbstraction
where T2 : class