1

I'm using NHibernate in conjunction with Repository Design Pattern. In current task, I need to update an entity and also delete another entity in the same transaction. I though about declare ISession.BeginTransaction() in Repository's Services layter and pass it to Repository's method as following:

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();
        }
    }
}

What I want to ask are

  1. Is it a good idea to let Repository's Service layer manage ISession as well as ITransaction and pass it around Associate Repository?
  2. If it's not a good idea, how should I change my design in order to perform those task in a same transaction without letting Repository's Service layer know about that transaction but still make Repository layer as lightweight as possible?

EDIT

For clarify, my EntityService is a business logic layer which depends on Repository to perform business logic then pass the result to presentation layer (a winform in my case). So that I thought that letting EntityService manage ISession and ITransaction will lead to tight coupling which I want to avoid in the first place.

EDIT 2

According to ptk93, I made some change to design as follow:

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();            
    }
}

Does this design enough for de-coupling Repository and Repository Service?

4

2 回答 2

1

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

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

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

于 2014-06-02T04:41:35.263 回答
1

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

话虽如此,我们的存储库基础中也有帮助管理事务,以便在您只更新一个存储库的情况下更容易使用存储库。

于 2014-06-02T06:20:13.073 回答