存储库服务应该知道交易信息吗?

时间:2014-06-02 03:14:51

标签: c# repository-pattern repository-design

我将NHibernate与Repository Design Pattern结合使用。在当前任务中,我需要更新实体并删除同一事务中的另一个实体。我虽然在ISession.BeginTransaction()打字机中声明Repository's Services并将其传递给Repository's method如下:

public class SomeEntity
{
    //entity's properties
}

public class EntityRepository : IEntityRepository
{
    public void update(ISession session, Entity entity)
    {
        session.Update(entity);
    }

    public void delete(ISession session, Entity entity)
    {
        session.Delete(entity);
    }
}

public class EntityService
{
    private IEntityRepository repository;

    public EntityService(IEntityRepository repository)
    {
        //I'm using Ninject for DI here
        this.repository = repository;
    }

    public void DoTask(Entity _updateEntity, Entity _deleteEntity)
    { 
        ISession session = NHibernateHelper.OpenSession();
        using(ITransaction transaction = session.BeginTransaction())
        {
            this.repositoy.update(session, _updateEntity);
            this.repositoy.delete(session, _deleteEntity);

            transaction.Commit();
        }
    }
}

我想问的是

  1. Repository's Service layer管理ISession以及ITransaction并传递Associate Repository是不是一个好主意?
  2. 如果这不是一个好主意,我应该如何更改我的设计,以便在同一个交易中执行这些任务,而不让Repository's Service layer知道该交易,但仍然将Repository layer设为尽量轻巧?
  3. 修改

    为了澄清,我的EntityServicebusiness logic layer,取决于Repository执行business logic然后将结果传递给presentation layer(在我的情况下是一个winform) )。因此我认为让EntityService管理ISessionITransaction将导致tight coupling我想首先避免。{1}}

    编辑2

    根据ptk93,我对设计进行了一些更改,如下所示:

    public class SomeEntity
    {
        //entity's properties
    }
    
    public class EntityRepository : IEntityRepository
    {
        private ISession session;
    
        private ITrasaction trasaction;
    
        public EntityRepository()
        {
            this.session = NHibernateHelper.OpenSession();
        }
    
        public void BeginTransaction()
        {
            if(this.transaction != null && this.transaciont.isActive)
            {
                throw new Exception();
            }
    
            this.transaction = this.session.BeginTransaction();
        }
    
        public void CommitTransaction()
        {
            if(this.transaction == null || this.transaction.isActive = false)
            {
                throw new Exception();
            }
    
            this.transaction.Commit();
            this.transaction.Dispose();
        }
    
        public void update(ISession session, Entity entity)
        {
            if(this.transaction == null || this.transaction.isActive = false)
            {
                throw new Exception();
            }
    
            session.Update(entity);
        }
    
        public void delete(ISession session, Entity entity)
        {
            if(this.transaction == null || this.transaction.isActive = false)
            {
                throw new Exception();
            }
    
            session.Delete(entity);
        }
    }
    
    public class EntityService
    {
        private IEntityRepository repository;
    
        public EntityService(IEntityRepository repository)
        {
            //I'm using Ninject for DI here
            this.repository = repository;
        }
    
        public void DoTask(Entity _updateEntity, Entity _deleteEntity)
        { 
            this.repository.BeginTransaction()
    
            this.repositoy.update(session, _updateEntity);
            this.repositoy.delete(session, _deleteEntity);
    
            this.repository.CommitTransaction();            
        }
    }
    

    这种设计是否足以解耦RepositoryRepository Service

2 个答案:

答案 0 :(得分:1)

您可以在边界和控制服务中分离您的服务。 边界对于客户端,网页等是可见的,并且控件仅对边界服务可见。您的存储库是否对客户端可见?似乎在您的用例中,存储库仅由其他服务使用,而不是客户端本身,因此它们是控件。 控件应该用MANDATORY标记,这样如果在没有启动事务的情况下调用它们,它们将抛出异常,并且从边界的方法的开头到结尾,事务必须是startend。

如果您使用控件/存储库UserRepository和AddressRepository创建具有三个地址的用户,则所有这些都将位于边界RegistrationService的注册方法开头的同一事务startend中。
如果要删除所有联系信息,则需要在具有不同事务边界的另一个名为ContactService的边界内使用控件AddressRepository和MailRepository。

此类决定取决于您的使用案例,但在我看来,实体控制边界模式可以满足您的需求。

答案 1 :(得分:1)

我个人更喜欢在服务中使用事务控制,因为有时您希望在同一事务中访问多个存储库,否则存储库可能会抛出异常而无法回滚与先前事务关联的更改。

虽然我们在我们的存储库库中也有帮助程序来管理事务,以便在只更新一个存储库的情况下更容易使用存储库。