在代理事务中封装数据库代码的一般方法?

时间:2014-12-04 09:57:12

标签: c# nhibernate delegates

我遇到了“问题”,我现在经常重复使用/ 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();
} );

我真的不喜欢这里的(session,session1 =&gt; ...)部分。看起来很混乱,有人可以在传递给委托的代码中使用 session 而不是 session1

基本上我的问题是。如果我放弃Action<ISession>并将其替换为Action,然后只在代码中使用 session ,它实际上会成为一个问题吗?我知道那里发生了很多魔术,但据我所知,如果我在委托代码中引用 session ,编译器会提供指向其中 session 对象的指针。或者某种或其他。我基本上可以使用它。

1 个答案:

答案 0 :(得分: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();
});