让Ninject管理我的交易状态,练习疑虑 [英] Letting Ninject manage my transaction state, practice concerns

查看:67
本文介绍了让Ninject管理我的交易状态,练习疑虑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

这种想法是,每个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后,需要提交它,以便二级缓存可以获取其结果.

有人可以阐明这一点吗?我终于走上正确的轨道了吗?还是我还是完全错过了要点?

解决方案

我不是专家(也没有ninject的经验),但是我同意您的三个结论,这就是我在项目中所做的. br> 我可以补充的另一件事是,我认为事务应按操作明确控制,而不是像代码所建议的那样全局控制(请求的开始和开始以及结束时提交).
这是因为我相信您希望分别控制每个操作的交易行为或不进行交易(或者,如果不需要数据库访问,甚至可能无法启动).
我使用的是管理层(或工作流,如果您愿意的话),它仅对此负责.例如:

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

希望这会有所帮助

I'm letting Ninject manage my ISession and ITransaction state in Fluent nHibnerate with the following registration method - I am wondering if it is sufficient control of transactions, or whether I need to be putting this somewhere else.

The thought is that each ISession is created on a request, and that Ninject handles the commit of everything done during that request.

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

I've examined the runtime using System.Diagnostics.Debug.WriteLine to write when things occur, and it does look like this is doing what I wanted it to do. What I am asking you, the community, is whether this is a good practice or not. Here is my understanding.

Countless hours of reading on http://ayende.com/blog/default.aspx has led me to re-evaluate a lot of the way I do session management.

A lot of digging into the nHibernate documentation tells me I need to use ITransaction every single time anything happens with my database.

Placing the management in an attribute is considered a flaw, since it does not adhere to the above mentioned statement.

Doing ITransaction per individual operation is not the correct process, because it would require either (A) my Controllers to have access to the ISession or (B) My IRepository<T> to have the ITransaction logic, which I have been told in previous questions was not a good practice.

Placing my ITransaction Management in an HttpModule adds un-neccessary overhead, since it gives my HttpContext knowledge of the ISession and it means I have to do some kind of injection into the HttpRequest (which I can do using [Inject], but it doesn't seem wise)

This has led me to this conclusion.

  • Transactions should start when an ISession is requested.
  • Everything that happens in a single request is encapsulated by one ISession
  • When an ITransaction is done, it needs to be committed so that the 2nd Level Cache can get its results.

Can anyone shed light on this? Am I finally on the right track? Or have I still missed the point completely?

解决方案

I'm no expert (and have no experience with ninject), but I do agree with your 3 conclusions, and that's what I do in my projects.
Another thing I can add is that, in my opinion, transactions should be controlled EXPLICITLY and per operation, and not globally (start and beginning of request and commit at the end) like your code suggests.
This is because I believe you want to control your transaction's behaviour- commit or not (or maybe not even start, if no DB access is necessary) for every operation individually.
What I use is a management (or workflow, if you prefer) layer, which is responsible just for that. for example:

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

hope this helps

这篇关于让Ninject管理我的交易状态,练习疑虑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆