让Ninject管理我的交易状态,实践顾虑

时间:2011-03-19 16:35:54

标签: nhibernate ninject

我让Ninject使用以下注册方法管理Fluent nHibnerate中的ISessionITransaction状态 - 我想知道它是否足以控制交易,或者我是否需要将其放入在其他地方。

我们的想法是在请求中创建每个ISession,并且Ninject会处理在该请求期间完成的所有操作的提交。

public class SessionModule : Ninject.Modules.NinjectModule
{
    private static ISessionFactory sessionFactory;

    public override void Load()
    {
        Bind<ISessionFactory>()
            .ToMethod(c => CreateSessionFactory())
            .InSingletonScope();

        Bind<ISession>()
            .ToMethod(c => OpenSession())
            .InRequestScope()
            .OnActivation(session =>
            {
                session.BeginTransaction();
                session.FlushMode = FlushMode.Commit;
            })
            .OnDeactivation(session =>
            {
                if (session.Transaction.IsActive)
                {
                    try
                    {
                        session.Flush();
                        session.Transaction.Commit();
                    }
                    catch
                    {
                        session.Transaction.Rollback();
                    }
                }
            });
    }

    /// <summary>
    /// Create a new <see cref="NHibernate.ISessionFactory"/> to connect to a database.
    /// </summary>
    /// <returns>
    /// A constructed and mapped <see cref="NHibernate.ISessionFactory"/>.
    /// </returns>
    private static ISessionFactory CreateSessionFactory()
    {
        if (sessionFactory == null)
            sessionFactory = Persistence.SessionFactory.Map
                (System.Web.Configuration
                    .WebConfigurationManager
                    .ConnectionStrings["Local"]
                    .ConnectionString
                );
        return sessionFactory;
    }

    /// <summary>
    /// Open a new <see cref="NHibernate.ISession"/> from a <see cref="NHibernate.ISessionFactory"/>.
    /// </summary>
    /// <returns>
    /// A new <see cref="NHibernate.ISession"/>.
    /// </returns>
    private static ISession OpenSession()
    {
        // check to see if we even have a session factory to get a session from
        if (sessionFactory == null)
            CreateSessionFactory();

        // open a new session from the factory if there is no current one
        return sessionFactory.OpenSession();
    }
}

我已经使用System.Diagnostics.Debug.WriteLine检查了运行时,以便在事情发生时进行编写,并且确实看起来像是在做想要它要做的事情。我要问你的是社区,这是否是一种良好的做法。这是我的理解。

http://ayende.com/blog/default.aspx上无数小时的阅读使我重新评估了我进行会话管理的方式。

大量深入研究nHibernate文档告诉我,每次我的数据库发生任何事情都需要ITransaction

将管理放在属性中被认为是一个缺陷,因为它不符合上述声明。

每个操作执行ITransaction不是正确的过程,因为它需要(A)我的控制器可以访问ISession或(B)我的IRepository<T> ITransaction逻辑,我在之前的问题中被告知这不是一个好习惯。

ITransaction管理放在HttpModule中会增加不必要的开销,因为它提供了我对HttpContext的ISession知识,这意味着我必须对HttpRequest进行某种注入。 [Inject](我可以使用ISession执行此操作,但这似乎并不明智)

这使我得出了这个结论。

  • 交易应在请求ISession时开始。
  • 单一请求中发生的所有事情均由一个 ITransaction
  • 封装
  • 当{{1}}完成后,需要提交它以便第二级缓存可以获得其结果。

任何人都可以对此有所了解吗?我终于走上了正轨吗?或者我还是完全错过了这一点?

1 个答案:

答案 0 :(得分:2)

我不是专家(并且对ninject没有经验),但我同意你的3个结论,这就是我在项目中所做的。
我可以添加的另一件事是,在我看来,交易应该是明确的和每个操作控制的,而不是全局的(开始和开始请求和最后提交),就像你的代码所暗示的那样。
这是因为我相信你想要控制你的交易的行为提交与否(或者如果不需要数据库访问,甚至可能无法启动)每个操作都是单独的。
我使用的是一个管理(或工作流程,如果你愿意)图层,它只负责这一点。例如:

public class SomeManager : ManagersBase
{
    public void DoSomething(DomainObject obj)
    {
        if (obj.Operation())
        {
            using (ITransaction tx = Session.BeginTransaction())
            {
                try
                {
                    Session.Update(obj);
                    tx.Commit();
                }
                catch (MeaningfulException ex)
                {
                    //handle
                    tx.Rollback();
                }
            }
        }
    }
}

希望这会有所帮助