工作单元模式——在哪里使用?

发布于 2024-12-26 19:00:41 字数 2164 浏览 2 评论 0原文

我正在使用 ASP.NET MVC 3,并使用 NHibernate 和 Ninject 的存储库和工作单元模式。我看了几个例子(12) 来帮助实现 UoW,我只是不确定应该在哪里使用该工作单元。是否应该将其注入到我的控制器中,并在我的操作中手动调用提交和回滚?

以下是一些代码示例:

工作单元(接口扩展 IDisposable 并具有会话、提交和回滚)

public class UnitOfWork : IUnitOfWork
{
    private readonly ISessionFactory _sessionFactory;
    private readonly ITransaction _transaction;

    public UnitOfWork(ISessionFactory sessionFactory)
    {
        _sessionFactory = sessionFactory;
        Session = _sessionFactory.OpenSession();
        Session.FlushMode = FlushMode.Auto;
        _transaction = Session.BeginTransaction(IsolationLevel.ReadCommitted);
    }

    public ISession Session { get; private set; }

    public void Commit()
    {
        if (!_transaction.IsActive)
        {
            throw new InvalidOperationException("No active transation");
        }

        _transaction.Commit();
    }

    public void Rollback()
    {
        if (_transaction.IsActive)
        {
            _transaction.Rollback();
        }
    }

    public void Dispose()
    {
        if (Session.IsOpen)
            Session.Close();
    }
}

我的 Ninject 模块的一部分:

Bind<IXXXRepository>().To<XXXRepository>().InRequestScope();
Bind<IYYYRepository>().To<YYYRepository>().InRequestScope();
...

Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
Bind<ISessionFactory>().ToMethod(x => NHibernateHelper.CreateConfiguration(Path.Combine(
            HostingEnvironment.ApplicationPhysicalPath,
            "bin",
            "hibernate.cfg.xml")).BuildSessionFactory()).InSingletonScope();

Bind<ISession>().ToMethod(x => x.Kernel.Get<IUnitOfWork>().Session).InRequestScope();

我的所有存储库都继承自一个注入 ISession 的类,正如我所说在这篇文章的前面,我将 IUnitOfWork 注入到我的控制器中,并根据需要调用 Commit 和 Rollback。我这样做对吗?我是否应该只在进行更新或删除时调用 Commit,并且根本不用担心为选择调用它?这会在每个请求结束时留下一个挂起的事务吗?

I'm using ASP.NET MVC 3 and am using the repository and unit of work patterns with NHibernate and Ninject. I looked at a couple examples (1, 2) to help implement UoW, and I'm just not sure where I should be using the unit of work. Should it be injected within my controllers, and manually call Commit and Rollback in my actions?

Here's some code examples:

Unit of work (interface extends IDisposable and has Session, Commit and Rollback)

public class UnitOfWork : IUnitOfWork
{
    private readonly ISessionFactory _sessionFactory;
    private readonly ITransaction _transaction;

    public UnitOfWork(ISessionFactory sessionFactory)
    {
        _sessionFactory = sessionFactory;
        Session = _sessionFactory.OpenSession();
        Session.FlushMode = FlushMode.Auto;
        _transaction = Session.BeginTransaction(IsolationLevel.ReadCommitted);
    }

    public ISession Session { get; private set; }

    public void Commit()
    {
        if (!_transaction.IsActive)
        {
            throw new InvalidOperationException("No active transation");
        }

        _transaction.Commit();
    }

    public void Rollback()
    {
        if (_transaction.IsActive)
        {
            _transaction.Rollback();
        }
    }

    public void Dispose()
    {
        if (Session.IsOpen)
            Session.Close();
    }
}

Part of my Ninject module:

Bind<IXXXRepository>().To<XXXRepository>().InRequestScope();
Bind<IYYYRepository>().To<YYYRepository>().InRequestScope();
...

Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
Bind<ISessionFactory>().ToMethod(x => NHibernateHelper.CreateConfiguration(Path.Combine(
            HostingEnvironment.ApplicationPhysicalPath,
            "bin",
            "hibernate.cfg.xml")).BuildSessionFactory()).InSingletonScope();

Bind<ISession>().ToMethod(x => x.Kernel.Get<IUnitOfWork>().Session).InRequestScope();

All my repositories inherit from a class that gets an ISession injected, and as I said earlier in the post I'm injecting the IUnitOfWork into my controllers and calling Commit and Rollback as necessary. Am I doing this right? Should I only be calling Commit when I'm doing updates or deletes, and don't worry about calling it at all for selects? Will that leave a hanging transaction at the end of every request?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

川水往事 2025-01-02 19:00:41

我喜欢使用 ActionFilter 围绕每个请求自动开始/提交工作单元。这对我 95% 的行为都很有效。对于一些更复杂的,我将注入 UoW 并从控制器或服务显式管理它。

我通常只是将 ISession 注入到 UnitOfWork 以及存储库中。存储库确实没有理由知道工作单元,它根本不应该接触事务。

I like to use an ActionFilter to automatically begin/commit the unit of work around every request. This works great for 95% of my actions. For the few more complex ones I'll inject the UoW and manage it explicitly from either the controller or the service.

I normally just inject the ISession to the UnitOfWork, as well as to the repositories. There's really no reason a repository should be aware of a unit of work, it shouldn't be touching the transaction at all.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文