我将NHibernate与存储库设计模式结合使用。在当前任务中,我需要在同一事务中更新一个实体并删除另一个实体。我想在Repository's Services
层声明ISession.BeginTransaction()
,并将其传递给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();
}
}
}
我想问的是
- 让
Repository's Service layer
管理ISession
以及ITransaction
并将其传递给Associate Repository
是一个好主意吗? - 如果这不是一个好主意,我应该如何改变我的设计,以便在同一个事务中执行这些任务,而不让
Repository's Service layer
知道该事务,但仍然使Repository layer
尽可能轻量级?
编辑
为了澄清,我的EntityService
是一个business logic layer
,它依赖于Repository
来执行business logic
,然后将结果传递给presentation layer
(在我的情况下是一个winform)。所以我认为让EntityService
管理ISession
和ITransaction
会导致tight coupling
,这是我首先要避免的。
编辑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();
}
}
这个设计是否足以解耦Repository
和Repository Service
?
你可以在边界和控制服务中分离你的服务。边界对客户端、网页等是可见的,而控件只对边界服务可见。您的存储库对客户端可见吗?在您的用例中,似乎存储库仅由其他服务而不是客户端本身使用,因此它们是控件。控件应该被标记为MANDATORY,这样如果在没有启动事务的情况下调用控件,并且在您的边界中从方法的开始到结束必须启动事务,那么它们将抛出异常。
在这种情况下,您正在使用控件/存储库UserRepository和AddressRepository创建具有三个地址的用户,它们都将在同一事务中开始于边界RegistrationService的register方法的开始。
如果要删除所有联系信息,AddressRepository和MailRepository控件必须在另一个名为ContactService的边界内使用,该边界具有不同的事务边界。
这样的决定取决于您的用例,但在我看来,实体-控制-边界模式可以满足您的需求。
我个人更喜欢在服务中具有事务控制,因为有时您希望在同一事务中访问多个存储库,否则存储库可能会抛出异常,无法回滚与前一个事务相关的更改。
已经说过,我们在库库库中也有帮助器来管理事务,以便在您只更新一个库的情况下更容易使用库。