gpt4 book ai didi

c# - UnitOfWork (NHibernate),一次只有一个事件的 UoW/ session ? (需要建议)

转载 作者:行者123 更新时间:2023-11-30 14:02:45 26 4
gpt4 key购买 nike

我正在使用 NHibernate、DI/IoC 和工作单元模式。

我见过的大多数 UoW 示例都确保在同一时间只能有一个事件的 UoW/ session ,例如 this onethis one .

不幸的是,我还不太明白我应该如何处理两个都使用 UoW 但一个调用另一个的服务。
举个例子:

使用 UoW 的记录器:

public class LoggerService : ILoggerService
{
private ILoggerRepository repo;

public LoggerService(ILoggerRepository Repo)
{
this.repo = Repo;
}

public void WriteLog(string message)
{
using (UnitOfWork.Start())
{
// write log
}
}
}

...以及另一个使用 UoW 并调用记录器的服务:

public class PlaceOrderService : IPlaceOrderService
{
private IOrderRepository repo;
private ILoggerService service;

public PlaceOrderService(IOrderRepository Repo, ILoggerService Service)
{
this.repo = Repo;
this.service = Service;
}

public int PlaceOrder(int orderNumber)
{
using (UnitOfWork.Start())
{
// do stuff

this.service.WriteLog("Order placed!"); // will throw exception!!

// do more stuff
}
}
}

如果我的 UoW 实现确保同时只有一个事件的 UoW(并且如果您尝试启动另一个 UoW 会抛出异常,就像在两个链接示例中一样),我的代码将在 this PlaceOrder 方法中的 .service.WriteLog 行:
已经有一个由 PlaceOrder 方法创建的事件 UoW,并且 WriteLog 方法将尝试打开第二个,因此 UoW 实现将因此抛出异常。

那么,我能做些什么呢?
我想到了两个想法,但在我看来都有些“hacky”。​​

  1. 不要在 LoggerService 中启动一个新的 UoW,而是假设在调用代码中已经有一个事件的 UoW。
    这就是我现在正在做的事情。我刚刚从 LoggerService 中删除了 using (UnitOfWork.Start()) 内容,并确保您不能直接调用 LoggerService,只能从其他服务调用。
    这意味着上面的代码可以工作,但如果调用代码不启动 UoW,LoggerService 将崩溃,因为 LoggerService 假定一个已经存在。

  2. 保持示例代码不变,但像这样更改 UoW.Start() 的实现:
    a) 如果没有活跃的UoW,开始一个新的
    b) 如果已经有一个活跃的UoW,返回这个
    这将使我能够直接从其他服务调用 LoggerService,无论是否已经存在 UoW。
    但是我从来没有在网络上的任何示例中看到过这样的事情。

(在这个例子中,只有两个服务。它可能会变得更复杂,想想一个 PlaceSpecialOrderService 做一些特殊事情的类然后调用 PlaceOrderService.PlaceOrder()...)

有什么建议吗?
提前致谢!


编辑:

感谢您到目前为止的回答。

好吧,也许日志记录不是最好的例子。
我理解您关于使用单独的 session 进行日志记录的观点,我会看一下并尝试一下。

无论如何,我仍然需要找到一种使嵌套服务调用起作用的方法。
想象一些其他示例而不是日志记录,例如我上面提到的 PlaceSpecialOrderService 示例。

对于建议我在基础设施中的某个地方而不是直接在服务中开始我的 UoW 的回答者:
一方面,这也是有道理的,但另一方面,这显然意味着我不能在一个服务调用中执行两个不同的事务。
我必须考虑一下,因为我很确定我会在某个地方需要它(比如:在一个交易中保存一个订单,然后在第二个交易中做更多的事情,即使失败了,订单也不会'回滚)。

您在您的应用中是否采用这种方式(每次服务调用一个 UoW)?
难道您不需要在同一服务调用中启动第二个 UoW 的可能性吗?

最佳答案

我想您已经发现了一个非常特殊的场景,您永远不应该将同一个 Session 用于业务服务和日志记录服务。 UnitOfWork 是“业务事务”,但日志记录显然不是事务的一部分。如果您的业务逻辑抛出异常,它将回滚您的日志!!!使用单独的 session 进行日志记录(使用单独的连接字符串限制在当前事务中登记)。

关于c# - UnitOfWork (NHibernate),一次只有一个事件的 UoW/ session ? (需要建议),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5365506/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com