我将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();
}
}
}
我想问的是
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
我想首先避免。{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();
}
}
这种设计是否足以解耦Repository
和Repository Service
?
答案 0 :(得分:1)
您可以在边界和控制服务中分离您的服务。 边界对于客户端,网页等是可见的,并且控件仅对边界服务可见。您的存储库是否对客户端可见?似乎在您的用例中,存储库仅由其他服务使用,而不是客户端本身,因此它们是控件。 控件应该用MANDATORY标记,这样如果在没有启动事务的情况下调用它们,它们将抛出异常,并且从边界的方法的开头到结尾,事务必须是startend。
如果您使用控件/存储库UserRepository和AddressRepository创建具有三个地址的用户,则所有这些都将位于边界RegistrationService的注册方法开头的同一事务startend中。
如果要删除所有联系信息,则需要在具有不同事务边界的另一个名为ContactService的边界内使用控件AddressRepository和MailRepository。
此类决定取决于您的使用案例,但在我看来,实体控制边界模式可以满足您的需求。
答案 1 :(得分:1)
我个人更喜欢在服务中使用事务控制,因为有时您希望在同一事务中访问多个存储库,否则存储库可能会抛出异常而无法回滚与先前事务关联的更改。
虽然我们在我们的存储库库中也有帮助程序来管理事务,以便在只更新一个存储库的情况下更容易使用存储库。