我想知道大多数人在处理存储库模式时,如果涉及多次访问同一个数据库(有时是事务性的),并且在维护数据库不可知性和同时使用多个存储库的同时有效地尝试这样做,我想知道。
假设我们有三个不同实体的存储库; Widget
,Thing
和Whatsit
。根据正常的解耦设计过程,每个存储库都通过基本接口进行抽象。然后,基本接口将是IWidgetRepository
,IThingRepository
和IWhatsitRepository
。
现在我们有了业务层或等价物(无论你想要什么叫它)。在这一层,我们有访问各种存储库的类。通常,这些类中的方法需要执行批处理/组合操作,其中涉及多个存储库。有时一个方法可以在内部使用另一个方法,而该方法仍然可以独立调用。那么,在这种情况下,当操作需要是事务性的时候呢?
示例:
class Bob
{
private IWidgetRepository _widgetRepo;
private IThingRepository _thingRepo;
private IWhatsitRepository _whatsitRepo;
public Bob(IWidgetRepository widgetRepo, IThingRepository thingRepo, IWhatsitRepository whatsitRepo)
{
_widgetRepo = widgetRepo;
_thingRepo= thingRepo;
_whatsitRepo= whatsitRepo;
}
public void DoStuff()
{
_widgetRepo.StoreSomeStuff();
_thingRepo.ReadSomeStuff();
_whatsitRepo.SaveSomething();
}
public void DoOtherThing()
{
_widgetRepo.UpdateSomething();
DoStuff();
}
}
如何有效地保持对该数据库的访问权限,并且在连接和无意中调用MSDTS等等时没有持续的开放 - 关闭 - 打开 - 关闭流?如果我的数据库类似于SQLite,那么创建嵌套事务的标准机制本身就会失败,但业务层不应该对这些问题感兴趣。
你如何处理这些问题? ADO.Net是否提供了简单的机制来处理这个问题,或者大多数人最终在ADO.Net周围包装他们自己的自定义代码来解决这些类型的问题?
答案 0 :(得分:1)
基本上你想为此使用UnitOfWork。我个人使用NHibernat e因为他们的ISession接口基本上是一个工作单元,所以它会将所有命令一起批处理并一起发送到数据库(还有其他的智能和对象状态跟踪,这有助于有了这个)。因此,发送到数据库的离散命令的数量将取决于您的ISession的生命周期。在Web上下文中,我通常使用Conversation Per Request,这意味着在请求开始时创建ISession,并在请求结束时刷新(发送到DB)。
根据您是否需要更短或更长的会话,这里有很多改变会话生命周期的潜力,如果需要,您还可以利用可以具有单独生命周期的事务。
答案 1 :(得分:1)
考虑到您的抽象存储库可以在任意数量的数据库中实现:SQLite,Microsoft SQL Server,直接文件访问等 - 即使您知道它们来自同一个数据库,它是“Bob”试图确保每个存储库可以相对于其他存储库进行事务处理是不合理的。
Bob 或许应该与包含存储库具体实现的 DoStuffService 进行对话。由于此服务正在创建存储库的具体实现,因此它能够创建适当的事务。然后,该服务将负责代表Bob安全地执行UnitOfWork(谢谢, ckramer )。