使用Repository模式、工作单元和autofac依赖注入实现webapi



开始使用Repository模式、工作单元和Autofac依赖注入开发web api。

体系结构就像

  1. Web API作为服务。

  2. 业务层(类库(-类似于将实体转换为DTO的业务逻辑。

  3. 数据访问层(类库(-存储库和UOW(工作单元(。

  4. 数据(类库(-实现实体框架。

我创建了通用存储库,并用特定的存储库进行了扩展,每个存储库都将具有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、中的构造函数注入

  1. 如果我将UOW作为另一个参数或参数传递,"UserRepository"将默认具有它。

  2. 如果注入两个库,它将如何处理。

  3. BAL SaveUser方法正在尝试使用UOW添加两个不同实体的值,此实现是否正确或需要进行任何修改?

  1. 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();
}
}
}
  1. 如果我将UOF作为另一个参数传递,或者参数"UserRepository"默认会有它

Autofac将负责创建具有正确依赖关系图的所有必需实例。你不必做任何特别的事情。

  1. 如果注入两个存储库,它将如何处理假设

Autofac将根据指定的生存期作用域处理它创建的所有实例。

当您使用InstancePerRequest时,Autofac将为每个新请求创建所需的实例,并在请求结束时自动处理所有创建的实例。

请参阅autofac文档中的生存期范围,以更好地了解生存期范围。

最新更新