C# 使用存储库模式、工作单元和autofac依赖项注入实现webapi

C# 使用存储库模式、工作单元和autofac依赖项注入实现webapi,c#,asp.net-web-api,autofac,repository-pattern,unit-of-work,C#,Asp.net Web Api,Autofac,Repository Pattern,Unit Of Work,开始使用存储库模式、工作单元和Autofac依赖项注入开发web api 建筑会像 webapi作为服务 业务层(类库)-将实体转换为DTO等业务逻辑 数据访问层(类库)-存储库和UOW(工作单元) 数据(类库)-实现实体框架 我创建了通用存储库并扩展了特定的存储库,每个存储库都有UOW。UOW由构造函数注入到存储库中 问题:从BAL中,存储库将由构造函数注入并分配到本地字段。我应该创建UOW并将其作为输入参数传递,还是由autofac处理 存储库 public class Repository

开始使用存储库模式、工作单元和Autofac依赖项注入开发web api

建筑会像

  • webapi作为服务

  • 业务层(类库)-将实体转换为DTO等业务逻辑

  • 数据访问层(类库)-存储库和UOW(工作单元)

  • 数据(类库)-实现实体框架

  • 我创建了通用存储库并扩展了特定的存储库,每个存储库都有UOW。UOW由构造函数注入到存储库中

    问题:从BAL中,存储库将由构造函数注入并分配到本地字段。我应该创建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);
            }
        }
    }
    
    UserRepository继承存储库类

    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;
            }
    
        }
    
    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;
            }
    
    公共类引导程序
    {
    公共静态无效运行()
    {
    //配置自动传真
    AutofacWebapiConfig.Initialize(全局配置.Configuration);
    }
    }
    专用静态IContainer注册表服务(ContainerBuilder builder)
    {
    //注册您的Web API控制器。
    RegisterAppController(Assembly.getExecutionGassembly());
    builder.RegisterType()
    .As()
    .InstancePerRequest();
    builder.RegisterType()
    .As()
    .InstancePerRequest();
    //将依赖项解析程序设置为Autofac。
    Container=builder.Build();
    返回容器;
    }
    
    从上面的示例中,UserRepository将从UserManager BAL中的构造函数注入

  • 如果我将UOW作为另一个参数或参数“UserRepository”传递,则默认情况下会将其传递

  • 如果注入两个位置,它将如何处理

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

  • 如果我将UOF作为另一个参数传递,默认情况下,参数“UserRepository”将具有它
  • Autofac将负责创建具有正确依赖关系图的所有必需实例。你不必做任何特别的事

  • 假设注入两个存储库,它将如何处理
  • Autofac将根据指定的生存期范围处理它创建的所有实例

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

    请参阅autofac文档,以更好地了解生命周期范围

  • 如果我将UOF作为另一个参数传递,默认情况下,参数“UserRepository”将具有它
  • Autofac将负责创建具有正确依赖关系图的所有必需实例。你不必做任何特别的事

  • 假设注入两个存储库,它将如何处理
  • Autofac将根据指定的生存期范围处理它创建的所有实例

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

    请参阅autofac文档,以更好地了解生命周期范围

  • 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;
        }
    
        // ...
    
     }
    
  • 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;
        }
    
        // ...
    
     }
    

    Cyril Durand,如何在BAL中调用Begin transaction,提交/回滚(来自上面的示例)?@user1645200有很多方法。你能更新这个问题并详细解释一下你需要什么和你迄今为止尝试了什么吗Cyril Durand,在BAL用户管理器类中更新了我的代码。SaveUser方法正在尝试使用UOW添加两个不同实体的值,此实现是否正确,或者是否需要进行任何修改?Cyril Durand,如何调用上述示例中的Begin transaction,在BAL中提交/回滚?@user1645200有许多方法可以做到这一点。你能更新这个问题并详细解释一下你需要什么和你迄今为止尝试了什么吗Cyril Durand,在BAL用户管理器类中更新了我的代码。SaveUser方法正在尝试使用UOW添加两个不同实体的值,此实现是否正确,或者是否需要进行任何修改?
    public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        protected IUnitOfWork UnitOfWork { get; }
    
        public Repository(IUnitOfWork unitOfWork)
        {
            UnitOfWork = unitOfWork;
        }
    
        // ...
    
     }
    
    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();
            }
        }
    }