我有一个使用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();
}
}
这是我的Repository实现:
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没有任何牵连的引用转换。
如何解决此错误?我的实现是否适用于自定义存储库?
答案 0 :(得分:1)
据我所知,您的UserAccountRepository
类定义可能存在错误:
public class UserAccountRepository<C> : GenericRepository<C>
where C : CSharpAssigmentContext, IUserAccountRepository
该类定义可以这样解读:
类型UserAccountRepository是泛型类型,其泛型参数类型为C; UserAccountRepository继承自泛型类GenericRepository,其泛型参数类型为C;类型C必须从类CSharpAssignmentContext继承,类型C必须实现接口IUserAccountRepository。
从泛型参数IUserAccountRepository
的类型约束中删除C
,并在逗号后面的GenericRepository之后添加它应该可以完成这项工作:
public class UserAccountRepository<C> : GenericRepository<C>, IUserAccountRepository
where C : CSharpAssigmentContext
类定义现在可以这样读: 类型UserAccountRepository是泛型类型,其泛型参数类型为C; UserAccountRepository继承自泛型类GenericRepository,其泛型参数类型为C;类型UserAccountRepository必须实现接口IUserAccountRepository。通用参数类型(类型C)必须从类CSharpAssignmentContext继承。
当你从泛型类/接口继承一个类和其他接口时,你必须首先指定你继承或实现的类型,然后才指定泛型类型约束:
public class SomeImplementation<T1, T2> : ISomeInterface<T1>, IAnotherInterface<T2>, IDisposable, ICloneable
where T1 : IAbstraction
where T2 : class
答案 1 :(得分:1)
基础是错误的。通用存储库应具有通用实体参数。您的“通用”存储库确实具有通用参数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图层,我认为没有任何理由与this standard example不同。除了包含多个存储库的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实现中,不会公开上下文。这是这个抽象层的目的之一。