2014-12-04 33 views
0

我跑进了“问题”,我是经常重复使用现在/ copy'n'pasting来检查,如果一个NHibernate的的Isession目前处于交易,如果不开始一个代码。将数据库代码与委托进行交易的一般方法?

现在,我认为这将是很好,如果我只是做了一个实用工具类的静态方法,我可以用的Isession对象,并包含实际的数据库代码的委托提供,然后只使用该方法来封装如果还没有一个正在进行的交易中的东西。

所以这就是我想出的。

public static class TransactionUtils 
{ 
    public static void EncloseInTransaction(ISession session, Action<ISession> codeToEnclose) 
    { 
     if (session == null) 
      throw new ArgumentNullException("session"); 

     var isInTrans = session.Transaction != null && session.Transaction.IsActive; 

     var tx = isInTrans ? session.Transaction : session.BeginTransaction(); 

     try 
     { 
      codeToEnclose(session); 

      if (!isInTrans) 
       tx.Commit(); 
     } 
     catch (Exception e) 
     { 
      tx.Rollback(); 
      throw; 
     } 
     finally 
     { 
      if (!isInTrans) 
       tx.Dispose(); 
     } 

    } 
} 

所以这一切都很好,我想。但使用该代码看起来像这样。

TransactionUtils.EncloseInTransaction(session, session1 => 
{ 
    session1.Query<Blahblah>().Where(x.Blub == "meh").ToList(); 
    session1.CreateQuery("update Foo set Urgs=:Moo where Id=:Id") 
     .SetParameter("moo", "baaahh") 
     .SetParameter("Id", 12305) 
     .ExecuteUpdate(); 
}); 

我真的不喜欢的(会话,会话1 => ...)这里一部分。看起来混乱的地狱,有人可以只使用传递给委托的代码里面会议而不是会话1

所以基本上我的问题是。它实际上是一个问题,如果我抛弃了Action<ISession>且仅Action代替它,然后只用里面的代码会议?我知道有很多神奇的发生。但我明白,如果我引用的代表代码中会议编译器提供一个指向里面就有了会议对象。或者其他什么。我基本上可以使用它。

+0

不能直接回答你的追求离子,但在你的例子中,显式使用会话没有意义,单个更新语句隐式地是事务性的,它将工作或失败。希望你在现实世界中不会像这样使用它,但我多次见过这种模式。 – 2014-12-04 10:06:59

+0

是的,这个例子非常简单。但处理隐式事务。我正在使用NHibernate Profiler,并且它始终将事务的隐式使用标记为可能的性能问题。所以我试图避免这一点。 – 2014-12-04 10:10:32

回答

1

可以作出这样的方法扩展方法,这应该使代码看起来更美观。

public static void EncloseInTransaction(this ISession session, Action<ISession> codeToEnclose) 

并调用方法:

session.EncloseInTransaction(s => 
{ 
    s.Query<Blahblah>().Where(x.Blub == "meh").ToList(); 
    s.CreateQuery("update Foo set Urgs=:Moo where Id=:Id") 
     .SetParameter("moo", "baaahh") 
     .SetParameter("Id", 12305) 
     .ExecuteUpdate(); 
}); 

您也可以使用Action像你说的(这是确定),它是这样的:

public static void EncloseInTransaction(this ISession session, Action codeToEnclose) 

调用方法:

session.EncloseInTransaction(() => 
{ 
    session.Query<Blahblah>().Where(x.Blub == "meh").ToList(); 
    session.CreateQuery("update Foo set Urgs=:Moo where Id=:Id") 
     .SetParameter("moo", "baaahh") 
     .SetParameter("Id", 12305) 
     .ExecuteUpdate(); 
}); 
+0

该死的......是啊!为什么我没有想到...非常感谢。 – 2014-12-04 10:05:11

+0

太棒了,欢迎您将问题标记为已回答:) – 2014-12-04 10:07:17

+0

我会尽快允许我。并感谢您进一步澄清。 – 2014-12-04 10:09:17