UoW应该实际处理什么?
按照我的看法,UoW不应处理提交和回滚。它仅应提供这样做的手段,并且仅应负责跟踪将要提交的对象的更改,这样,如果它们处于某种不一致的状态或发生了某些更改,则事务应该失败吗?
所以我看到UoW的方式是这样的。
public interface IUnitOfWork : IDisposable
{
IAtomicTransaction BeginTransaction();
Task<object> SaveAsync<TEntity>(TEntity entity);
Task UpdateAsync<TEntity>(TEntity entity);
Task RemoveAsync<TEntity>(TEntity entity);
}
上班应该是这样的
interface IAtomicTransaction : IDisposable
{
void Commit();
void Rolleback();
}
例如,这篇文章(不仅是这篇文章,而且还有很多类似的文章),
如果您看到的话,您会发现它在存储库中使用了ISession,我发现这是一个错误,因为它将直接将存储库(您的业务)链接到NHibernate的ISession。 UoW不应该承担这项责任吗?是否应该因为更改框架而开始更改业务实现? UoW是否不应该充当适配器,例如反腐败层?
答案 0 :(得分:1)
UoW不仅仅是交易,more。以下是来自Martin Fowler的引用:
工作单元会跟踪您在业务交易过程中可能影响数据库的所有操作。完成后,它会根据您的工作找出更改数据库所需要做的一切。
它应该:
internal
构造函数的存储库以及UoW中的某些类似于工厂的方法都会创建存储库。interface IUnitOfWork : IDisposable
{
IDbConnection Connection { get; }
IDbTransaction Transaction { get; }
void Begin();
void Commit();
void Rollback();
IRepository CreateRepository(....);
}
方法CreateRepository
在此UoW下创建一个存储库实例。这样,您可以在多个存储库中共享相同的UoW。这样,一个数据库事务可以分布在多个存储库中。另一种选择是将UoW注入到存储库中,如图here所示。
此方法的问题在于,它不会强制出现问题。呼叫者取决于何时(或是否)开始交易。
我可以想象的其他迷你版本的UoW(强制使用UoW)如下所示:
public sealed class UoWSession
{
public UoWSession()
{
//Open connection here
//Begin transaction here
}
IRepository CreateRepository(....)
{
//Create and return the requested repository instance here
}
void Commit()
{
transaction.Commit();
}
void Dispose()
{
//If transaction is not commited, rollback it here.
//Cleanup resources here.
}
}
在不使用ORM的情况下,您必须公开某些内容,该内容告诉您一切都很好。以上实现使用Commit
方法。
可能有一个简单的属性,让我们说IsAllWell
(默认情况下为false
,并调用代码对其进行显式设置)。然后,您的Dispose
方法基于属性来提交或回滚事务。在这种情况下,您不需要公开Commit
方法,因为您正在标记内部对其进行处理。
答案 1 :(得分:1)
现在您已经编辑了问题,所以我必须更改回答方式;因此,第二个答案。我的first answer仍然很有价值(希望;))。
UoW应该自动找出需要清除的更改(如果有)。
IAtomicTransaction BeginTransaction(); void Commit(); void Rolleback();
上述方法可能是UoW的一部分,也可能不是。 UoW的许多实现都公开了这些内容。暴露那些缺点是,事务处理成为调用者的责任;不是你的班级。还有一点是,呼叫者可以更好地控制该过程。
如果您想绕过缺点,请参阅我的第一个答案中的替代方法。
Task<object> SaveAsync<TEntity>(TEntity entity); Task UpdateAsync<TEntity>(TEntity entity); Task RemoveAsync<TEntity>(TEntity entity);
以上方法是存储库的一部分。这些不能成为UoW的一部分。 UoW应该基于更改跟踪自动找出要做什么。如果我们仅将讨论限制在数据库事务中,那么DbTransaction
可以正确处理。有关处理变更跟踪的更多详细方法,请参阅我的第一个答案。
以下是基于NHibernate的实现。请注意,这是not recommended 。如果您使用的是完整的ORM,则应避免这种类型的实现,因为这对您的设计几乎没有价值。 如果仅将ISession
替换为IDbConnection
,则也可以使用ADO.NET来实现。
public interface IUnitOfWork : IDisposable
{
void Flush();
}
public sealed class UnitOfWork : IUnitOfWork
{
public UnitOfWork()
{
session = SessionFactroyHelper.CreateSession();
transaction = session.BeginTransaction();
}
ISession session = null;
ITransaction transaction = null;
void IUoWSession.Flush()
{
transaction.Commit();
}
void IDisposable.Dispose()
{
transaction.Dispose();
transaction = null;
session.Dispose();
session.Dispose();
}
}
顺便说一句,这个主题本身就是基于意见的。如何实现UoW和存储库是个人设计的决定。如果您真的很想实现 correct (?)UoW,请考虑在代码中绕过UoW包装器直接使用一些高级ORM。