将数据库代码包含在带有委托的事务中的常规方法

本文关键字:事务 方法 常规 代码 数据库 包含 | 更新日期: 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();
});