我正在使用 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(并且在您尝试启动另一个时抛出异常,就像在两个链接的示例中一样),我的代码将在 PlaceOrder 方法的 this.service.WriteLog 行中崩溃:
PlaceOrder 方法已经创建了一个事件的 UoW,WriteLog 方法将尝试打开第二个,因此 UoW 实现将因此抛出异常。

那么,我能做些什么呢?
我想出了两个想法,但对我来说这两个想法都有些“hacky”。
  • 不要在 LoggerService 中启动一个新的 UoW,而是假设调用代码中已经有一个事件的 UoW。
    这就是我目前正在做的事情。我刚刚从 LoggerService 中删除了 using (UnitOfWork.Start()) 内容,并确保您不能直接调用 LoggerService,只能从其他服务调用。
    这意味着上面的代码可以工作,但如果调用代码没有启动 UoW,LoggerService 将崩溃,因为 LoggerService 假定一个已经存在。
  • 保持示例代码不变,但像这样更改 UoW.Start() 的实现:
    a) 如果没有事件的 UoW,则开始一个新的 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/

    10-12 14:03