将数据库代码包含在带有委托的事务中的常规方法
本文关键字:事务 方法 常规 代码 数据库 包含 | 更新日期: 2023-09-27 18:33:14
我遇到了一个"问题",我现在经常重用/复制粘贴代码,以检查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
替换它,然后只在代码中使用会话,这真的会是一个问题吗?我知道那里发生了很多魔术,但据我所知,如果我在委托代码中引用会话,编译器会提供指向其中会话对象的指针。或其他东西。我基本上可以用它。
你可以使该方法成为扩展方法,这应该使代码看起来更好。
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();
});