开始使用Repository模式、工作单元和Autofac依赖注入开发web api。
体系结构就像
-
Web API作为服务。
-
业务层(类库(-类似于将实体转换为DTO的业务逻辑。
-
数据访问层(类库(-存储库和UOW(工作单元(。
-
数据(类库(-实现实体框架。
我创建了通用存储库,并用特定的存储库进行了扩展,每个存储库都将具有UOW。UOW由构造函数注入到存储库中。
问题:从BAL,Repository将由构造函数注入并分配到本地字段。如果我创建UOW并将其作为输入参数传递,或者autofac将处理此问题。
仓库,
public class Repository<TEntity>:IRepository<TEntity> where TEntity:class
{
protected readonly DbContext Context;
public Repository(IUnitOfWork unitOfWork)
{
Context = unitOfWork.TMSContext;
}
public TEntity Get(int id)
{
return Context.Set<TEntity>().Find(id);
}
public IEnumerable<TEntity> GetAll()
{
return Context.Set<TEntity>().ToList();
}
public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
return Context.Set<TEntity>().Where(predicate);
}
public TEntity SingleOrDefault(Expression<Func<TEntity, bool>> predicate)
{
return Context.Set<TEntity>().SingleOrDefault(predicate);
}
public void Add(TEntity entity)
{
Context.Set<TEntity>().Add(entity);
}
public void AddRange(IEnumerable<TEntity> entities)
{
Context.Set<TEntity>().AddRange(entities);
}
public void Remove(TEntity entity)
{
Context.Set<TEntity>().Remove(entity);
}
public void RemoveRange(IEnumerable<TEntity> entities)
{
Context.Set<TEntity>().RemoveRange(entities);
}
}
}
工作单元,
public class UnitOfWork:IUnitOfWork
{
private DbContext _dbContext;
private DbContextTransaction _objTran;
protected IDbFactory DbFactory
{
get;
private set;
}
DbContext IUnitOfWork.TMSContext
{
get { return _dbContext ?? (_dbContext = DbFactory.Init()); }
}
public UnitOfWork(IDbFactory dbFactory)
{
DbFactory = dbFactory;
}
public int SaveCahnges()
{
return _dbContext.SaveChanges();
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_dbContext.Dispose();
}
}
public void BeginTransaction()
{
_objTran = _dbContext.Database.BeginTransaction();
}
public void Commit()
{
_objTran?.Commit();
}
public void Rollback()
{
_objTran?.Rollback();
_objTran?.Dispose();
}
}
UserRepository继承Repository类
public class UserRepository : Repository<User>, IUserRepository
{
IUnitOfWork _unitOfWork;
public UserRepository(IUnitOfWork unitOfWork):base(unitOfWork)
{
_unitOfWork = unitOfWork;
}
public bool ValidateUser(string userName, string password)
{
var res = SingleOrDefault(x => x.UserName == userName && x.UserPwd == password);
return res != null;
}
}
在BAL实现中,
public class UserManager : IUserManager
{
private IUserRepository _userRepository;
private IAddressRepository _addressRepository;
private IUnitOfWork _unitOfWork;
public UserManager(IUnitOfWork unitOfWork, IUserRepository userRepository, IAddressRepository addressRepository)
{
_unitOfWork = unitOfWork;
_userRepository = userRepository;
_addressRepository = addressRepository;
}
public bool ValidateUser(string userName, string password)
{
return _userRepository.ValidateUser(userName, password);
}
public void SaveUser(UserDTO userDTO, AddressDTO addressDTO)
{
try
{
_unitOfWork.BeginTransaction();
_userRepository.Add(ConvertToUser(userDTO));
_unitOfWork.SaveCahnges();
_addressRepository.Add(ConvertToAddress(addressDTO));
_unitOfWork.SaveCahnges();
_unitOfWork.Commit();
}
catch (Exception)
{
_unitOfWork.Rollback();
}
}
}
WebAPI控制器,
public class UserController : ApiController
{
IUserManager _userManager;
public UserController(IUserManager userManager)
{
_userManager = userManager;
}
[HttpGet]
public bool ValidateUser(string userName, string password)
{
return _userManager.ValidateUser(userName, password);
}
}
AutoFac、
public class Bootstrapper
{
public static void Run()
{
//Configure AutoFac
AutofacWebapiConfig.Initialize(GlobalConfiguration.Configuration);
}
}
private static IContainer RegisterServices(ContainerBuilder builder)
{
//Register your Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<TMSDataEntities>()
.As<DbContext>()
.InstancePerRequest();
builder.RegisterType<DbFactory>()
.As<IDbFactory>()
.InstancePerRequest();
//Set the dependency resolver to be Autofac.
Container = builder.Build();
return Container;
}
从上面的例子中,UserRepository将从UserManagerBAL、中的构造函数注入
如果我将UOW作为另一个参数或参数传递,"UserRepository"将默认具有它。
如果注入两个库,它将如何处理。
BAL SaveUser方法正在尝试使用UOW添加两个不同实体的值,此实现是否正确或需要进行任何修改?
- BAL SaveUser方法正在尝试使用UOW添加两个不同实体的值,此实现是否正确或是否有任何修改是否需要
您可以在通用存储库中使用UnitOfWork,而不是DbContext。在这种情况下,您将始终可以从每个存储库类访问UOW。
回到这个问题,UOW并不是只引用一个实体,而是引用整个dbContext和SaveChanges((方法来保存对dbContext中所有实体的更改。在SaveUser((方法中,您不需要从UOW调用SaveChanges((方法两次。您必须记住在提交事务之前调用SaveChanges((。
您的通用存储库类应该如下所示:
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected IUnitOfWork UnitOfWork { get; }
public Repository(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
// ...
}
和您的UserManager类:
public class UserManager : IUserManager
{
private IUserRepository _userRepository;
private IAddressRepository _addressRepository;
public UserManager(IUserRepository userRepository,
IAddressRepositoryaddressRepository)
{
_userRepository = userRepository;
_addressRepository = addressRepository;
}
public bool ValidateUser(string userName, string password)
{
return _userRepository.ValidateUser(userName, password);
}
public void SaveUser(UserDTO userDTO, AddressDTO addressDTO)
{
try
{
// Is doesn't matter if you use _userRepository or _addressRepository,
// because this classes use the same UnitOfWork.
_userRepository.UnitOfWork.BeginTransaction();
_userRepository.Add(ConvertToUser(userDTO));
_addressRepository.Add(ConvertToAddress(addressDTO));
_userRepository.UnitOfWork.SaveCahnges();
_userRepository.UnitOfWork.Commit();
}
catch (Exception)
{
// Todo - log exception
_userRepository.UnitOfWork.Rollback();
}
}
}
- 如果我将UOF作为另一个参数传递,或者参数"UserRepository"默认会有它
Autofac将负责创建具有正确依赖关系图的所有必需实例。你不必做任何特别的事情。
- 如果注入两个存储库,它将如何处理假设
Autofac将根据指定的生存期作用域处理它创建的所有实例。
当您使用InstancePerRequest
时,Autofac将为每个新请求创建所需的实例,并在请求结束时自动处理所有创建的实例。
请参阅autofac文档中的生存期范围,以更好地了解生存期范围。