代码之家  ›  专栏  ›  技术社区  ›  Kgn-web

如何用EF6在C_中实现UOW

  •  0
  • Kgn-web  · 技术社区  · 8 年前

    我正在尝试在我的应用程序中使用存储库模式实现UOW。

    虽然独立的存储库已经就位,但当一个事务(UOW)中有多个存储库时,却让我抓狂。

    EF Relation One Customer - Many CustomerContacts
    

    单位工程

     public interface IUnitOfWork
        : IDisposable
    {
        void InitTransaction();
    
        void Rollback();
    
        void CommitTransaction();
    
    }
    

    基辅

     public class UnitOfWork :
        IUnitOfWork
    {
    
        protected DbContextTransaction _transaction;
    
    
        #region IUnitOfWork
    
         public void CommitTransaction()
        {
            _transaction.UnderlyingTransaction.Commit();
        }
    
        public void Rollback()
        {
            _transaction.UnderlyingTransaction.Rollback();
        }
        #endregion IUnitOfWork
    }
    

    顾客

     public class CustomerUOW
        : UnitOfWork
    {
        private IRepository<CustomerRepository> _customerRepository;
        private IRepository<CustomerContactRepository> _customerContactRepository;
    
        public BranchUOW(IRepository<CustomerRepository> customerRepository, 
            IRepository<CustomerContactRepository> customerContactRepository)
        {
            _customerRepository= customerRepository;
            _customerContactRepository= customerContactRepository;
        }
        public override void InitTransaction()
        {
            _transaction.Commit();
        }
    
    
    }
    

    如何实现 CustomerUOW 以便 Customer &安培 CustomerContact 存储库共享同一个dbcontext 交易?是吗?

    注意:每个存储库在各自的类中都有一个crud的实现。喜欢

     public class EntityRepository<C, T>
       : BaseRepository<FoodieTenantContext, T>
        where T : class
        where C : CustomerContext
    {
        private DbSet<T> _dataSet
        {
            get
            {
                return _ctx.Set<T>();
            }
        }
    
        public EntityRepository(FoodieTenantContext ctx)
            : base(ctx)
        {
        }
    
        public override void Add(T entity)
        {
            _dataSet.Add(entity);
        }
    
        public override void Delete(T entity)
        {
            throw new NotImplementedException();
        }
    
        public override IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
        {
            return _dataSet.Where(predicate).ToList<T>();
        }
    
        public override IEnumerable<T> GetAll()
        {
            return _dataSet.ToList<T>();
        }
    
        public override IQueryable<T> GetQuery()
        {
            return _dataSet;
        }
    
        public override int Save()
        {
            return _ctx.SaveChanges();
        }
    
        public override T Single(Expression<Func<T, bool>> predicate)
        {
            return _dataSet.Where(predicate).SingleOrDefault();
        }
    
        public override void Update(T entity)
        {
            _dataSet.Attach(entity);
            _ctx.Entry<T>(entity).State = EntityState.Modified;
        }
    }
    

    谢谢

    1 回复  |  直到 8 年前
        1
  •  1
  •   Michal Ciechan    8 年前

    在路上会提供一个 Func<FoodieTenantContext, IRepository<CustomerContactRepository>> 在您的客户群中

    public abstract class UnitOfWork : IUnitOfWork
    {
        public UnitOfWork(FoodieTenantContext context)
        {
            this.Context = context;
        }
    
        // ... rest of the class
    }
    
    // usage could be like the following
    
    public class CustomerUOW : UnitOfWork
    {
        public CustomerService(Func<FoodieTenantContext, IRepository<CustomerRepository>> customerRepo
            , Func<FoodieTenantContext, IRepository<CustomerContactRepository>> contactRepo
            , FoodieTenantContext context) 
            : (context)
        {        
            _customerRepo = customerRepo(context);
            _contactRepo = contactRepo(context);
        }
    }
    

    另一个选择是创建RepositoryFactory,但这意味着您必须公开 Context 属性从 IRepository<T>

    public class RepositoryFactory
    {
        IServiceProvider _ioc; // This would be your IoC/DI Container
    
        public RepositoryFactory(IServiceProvider ioc)
        {
            _ioc = ioc;
        }
    
        // Resolve T passing in the provided `FoodieTenantContext` into the constructor
        public IRepository<T> CreateRepository<T>(FoodieTenantContext context) =>
            _ioc.Resolve<T>(context); 
    
    }
    

    另一个解决方案可能是(我最不喜欢的)公开 RepositoryFactory 对于每种类型 在职的

    public class RepositoryFactory
    {
        public IRepository CreateCustomerContactRepository(FoodieTenantContext context) => 
            return new CustomerContactRepository(context);
    }
    

    在温莎城堡注册func

    根据评论,注册 Func<T> 在Castle.Windsor中,您可以尝试以下内容,它是 Anton's answer to Func injecting with Windsor container question. 是的。(我现在无法测试)

    Container.Register(
    
      Component.For<Func<FoodieTenantContext, IRepository<CustomerRepository>>>()
               .Instance((FoodieTenantContext context) => Container.Resolve<IRepository<CustomerRepository>>(new {context = context}))
    )
    

    否则你可以试着玩 AsFactory() 是的。了解更多信息 read Windsor documentation

    最后,您可以手动创建工厂或切换支持ioc/di的容器 Func<[TIn1, TIn2, ...], T> 开箱即用,或者至少是本地的。