C# 在与委托的事务中封装数据库代码的一般方法?

C# 在与委托的事务中封装数据库代码的一般方法?,c#,nhibernate,delegates,C#,Nhibernate,Delegates,我遇到了一个“问题”,我现在经常重用/复制粘贴代码来检查nHibernate会话当前是否在事务中,如果没有,则启动一个事务 现在我想,如果我在一个实用程序类中创建一个静态方法,我可以提供一个ISession对象和一个包含实际数据库代码的委托,然后使用该方法将这些东西封装在一个事务中(如果还没有事务进行中的话) 这就是我想到的 public static class TransactionUtils { public static void EncloseInTransaction(ISe

我遇到了一个“问题”,我现在经常重用/复制粘贴代码来检查nHibernate会话当前是否在事务中,如果没有,则启动一个事务

现在我想,如果我在一个实用程序类中创建一个静态方法,我可以提供一个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
{
public static void EncloseInTransaction(ISession会话,操作代码关闭)
{
if(会话==null)
抛出新异常(“会话”);
var isInTrans=session.Transaction!=null&&session.Transaction.IsActive;
var tx=isInTrans?session.Transaction:session.BeginTransaction();
尝试
{
代码关闭(会话);
如果(!isInTrans)
tx.Commit();
}
捕获(例外e)
{
tx.回滚();
投掷;
}
最后
{
如果(!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();
} );
TransactionUtils.EncloseInTransaction(会话,会话1=>
{
session1.Query().Where(x.Blub==“meh”).ToList();
会话1.CreateQuery(“更新Foo set Urgs=:Moo,其中Id=:Id”)
.SetParameter(“moo”、“baah”)
.SetParameter(“Id”,12305)
.ExecuteUpdate();
} );
我真的不喜欢这里的(session,session1=>…)部分。看起来很混乱,有人可以在传递给委托的代码中使用session而不是session1


所以基本上我的问题是。如果我放弃了
操作
而只使用
操作
替换它,然后只在代码中使用会话,这会是一个问题吗?我知道那里发生了很多奇妙的事情,但据我所知,如果我在委托代码中引用会话,编译器会提供一个指向其中会话对象的指针。或者别的什么。我基本上可以用这个

您可以将该方法作为扩展方法,这将使代码看起来更好

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();
});
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();
});
session.EncloseInTransaction(()=>
{
session.Query().Where(x.Blub==“meh”).ToList();
CreateQuery(“更新Foo set Urgs=:Moo,其中Id=:Id”)
.SetParameter(“moo”、“baah”)
.SetParameter(“Id”,12305)
.ExecuteUpdate();
});

该死的。。。是 啊为什么我没想到。。。非常感谢。我一有空就去。感谢您进一步澄清。这不是对您问题的直接回答,但在您的示例中,显式使用会话没有意义,单个update语句是隐式事务性的,它要么工作,要么失败。希望你在现实世界中没有像这样使用它,但我已经多次看到这种模式。是的,这个例子非常简单。但解决隐含的交易。我正在使用NHibernate Profiler,它总是将事务的隐式使用标记为一个可能的性能问题。所以我尽量避免这样。
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();
});