让Ninject管理我的交易状态,实践问题

Cie*_*iel 11 nhibernate ninject

我让Ninject管理我ISessionITransaction状态良好nHibnerate与下列注册方法-我想知道,如果它是交易的足够的控制,或者我是否需要别人把这个地方.

我们的想法是每个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();
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经检查了运行时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完成,它需要致力于使二级高速缓存可以得到它的结果.

任何人都可以阐明这一点吗?我终于走上了正轨吗?或者我还是完全错过了这一点?

J. *_* Ed 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();
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助