Nhibernate 让Ninject管理我的事务状态、实践关注点

Nhibernate 让Ninject管理我的事务状态、实践关注点,nhibernate,ninject,Nhibernate,Ninject,我让Ninject使用以下注册方法在Fluent NHiberate中管理我的ISession和ITransaction状态-我想知道这是否足以控制事务,或者我是否需要将其放在其他地方 其思想是,每个ISession都是根据请求创建的,而Ninject处理在该请求期间完成的所有提交 public class SessionModule : Ninject.Modules.NinjectModule { private static ISessionFactory sessionFacto

我让Ninject使用以下注册方法在Fluent NHiberate中管理我的
ISession
ITransaction
状态-我想知道这是否足以控制事务,或者我是否需要将其放在其他地方

其思想是,每个
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();
    }
}
public类SessionModule:Ninject.Modules.Ninject模块
{
私人静态ISessionFactory sessionFactory;
公共覆盖无效负载()
{
绑定()
.ToMethod(c=>CreateSessionFactory())
.InSingletonScope();
绑定()
.ToMethod(c=>OpenSession())
.InRequestScope()
.OnActivation(会话=>
{
session.BeginTransaction();
session.FlushMode=FlushMode.Commit;
})
.OnDeactivation(会话=>
{
if(session.Transaction.IsActive)
{
尝试
{
session.Flush();
Commit();
}
抓住
{
session.Transaction.Rollback();
}
}
});
}
/// 
///创建新数据库以连接到数据库。
/// 
/// 
///一个构造和映射的模型。
/// 
私有静态ISessionFactory CreateSessionFactory()
{
if(sessionFactory==null)
sessionFactory=Persistence.sessionFactory.Map
(System.Web.Configuration)
.WebConfiguration Manager
.连接字符串[“本地”]
.连接字符串
);
返回工厂;
}
/// 
///从中打开一个新的。
/// 
/// 
///一个新的。
/// 
私有静态ISession OpenSession()
{
//检查是否有会话工厂可以从中获取会话
if(sessionFactory==null)
CreateSessionFactory();
//如果没有当前会话,请从工厂打开新会话
返回sessionFactory.OpenSession();
}
}
我已经使用
System.Diagnostics.Debug.WriteLine
检查了运行时,以便在事情发生时进行写入,它确实执行了我希望它执行的操作。我要问的是社区,这是否是一种良好的做法。这是我的理解

无数个小时的阅读让我重新评估了很多会话管理的方法

对nHibernate文档的大量挖掘告诉我,每当数据库发生任何事情时,我都需要使用
ITransaction

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

每个操作执行
ITransaction
都不是正确的过程,因为它需要(A)我的控制器访问
ISession
或(B)我的
IRepository
拥有
ITransaction
逻辑,我在前面的问题中被告知这不是一个好做法

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

这使我得出了这个结论

  • 事务应在请求
    ISession
    时启动
  • 在一个请求中发生的每件事都被一个
    ISession
  • ITransaction
    完成时,需要提交它,以便二级缓存可以获得其结果
有人能解释一下吗?我终于走上正轨了吗?还是我仍然完全没有抓住要点

我不是专家(也没有ninject的经验),但我同意你的3个结论,这就是我在项目中所做的。
我可以补充的另一点是,在我看来,事务应该按照操作进行显式控制,而不是像代码所建议的那样进行全局控制(请求的开始和开始,最后提交)。
这是因为我相信您希望控制事务的行为—每个操作是否提交(如果不需要DB访问,甚至可能不启动)。
我使用的是一个管理层(或者工作流,如果你愿意的话),它负责这一点。例如:

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();
                }
            }
        }
    }
}

希望这能有所帮助

我很抱歉没有早点接受。我以为我已经处理好了。非常感谢。我想知道是否有一种方法可以挂接到RequestScope中的
以启动/提交事务。。。谢谢你的帖子!