C# NHibernate:你总是要承诺吗?它在阅读时实际上做了什么?

C# NHibernate:你总是要承诺吗?它在阅读时实际上做了什么?,c#,.net,nhibernate,C#,.net,Nhibernate,我正在使用NHibernate与我的C#.NET项目中的数据库进行通信。当与数据库通信时,我是否总是必须提交事务?在进行读取时,这实际上做了什么?我发现自己在阅读时偶尔会忘记承诺,但一切似乎都很好 using (var tx = Session.BeginTransaction()) { var fromDb = Session.Get<User>(user.Id); Assert.AreEqual(user.Id, fromDb.Id); tx.Commit

我正在使用NHibernate与我的C#.NET项目中的数据库进行通信。当与数据库通信时,我是否总是必须提交事务?在进行读取时,这实际上做了什么?我发现自己在阅读时偶尔会忘记承诺,但一切似乎都很好

using (var tx = Session.BeginTransaction())
{
    var fromDb = Session.Get<User>(user.Id);
    Assert.AreEqual(user.Id, fromDb.Id);
    tx.Commit(); // <-- Necessary?? 
}
使用(var tx=Session.BeginTransaction())
{
var fromDb=Session.Get(user.Id);
aresequal(user.Id,fromDb.Id);

tx.Commit();//提交或回滚事务是个好主意:

开始事务启动本地事务 发送连接的事务 声明。取决于 当前事务隔离级别 设置,获取许多资源以 支持Transact-SQL语句 由连接发出的消息被锁定 直到交易完成为止 使用提交事务或 回滚事务语句。 长期未完成的交易 一段时间可以防止其他问题 用户无法访问这些已锁定的文件 资源,也可以防止日志 截断


如果您仅在事务期间读取,为什么要启动事务? 这完全没有必要

尽管如此,如果您将连接释放模式设置为“after_transaction”,则只有在提交或回滚事务后,连接才会关闭。因此,在这些情况下,如果您希望执行多个读取操作,启动事务确实很方便

事实上,我主要做的是:

Person p = null;
using( ISession s = sf.OpenSession())
{
    With.Transaction (s, () => p = s.Get (1));
}
比如说

其中,“
With.Transaction
”是一种实用方法,用于启动事务,执行传递的委托(操作),然后提交或回滚事务

它看起来非常像这样:

public static class With
{
    public static void Transaction( ISession s, Action proc )
    {
        using( ITransaction thx = s.BeginTransaction () )
        {
            try
            {
                proc();
                thx.Commit();
            }
            catch
            {
                 thx.Rollback();
                 throw;
            }
        }
    }
}
但是,我的实现仍然略有不同,因为我没有直接使用NHibernate的
ISession
。 相反,我在
会话
周围创建了一个包装器,在该包装器中,我还跟踪该会话的当前事务(如果有)。 通过这样做,在
With.Transaction
方法中,我可以检查会话是否已经有活动事务,然后,我只在没有活动事务的情况下启动事务


(Ayende的
和.Transaction
创意都有学分)。

哦,我想真正的问题是“我需要一个交易来阅读吗?”-听起来你的答案是“不”?谢谢你的示例代码-看起来不错!所以你实际上必须使用一个事务?我尝试在我的示例中删除该事务,但是它在读取时找不到对象。嗯…我和ReSharper都找不到With关键字。你介意给我一个在哪里找到它的提示吗?对不起,我忘了提到。这是一个定制的类。啊,that解释了这一点。那么-我确实需要一个事务?也用于读取?并且我确实需要提交或回滚每个事务以确保释放所有资源?即使我有一个using,它将处理该事务?正确吗?因此我必须提交()或回滚()即使我有using子句来处理每一笔交易?可能已经太晚了,但答案实际上并没有回答问题,只是猜测一下这个和那个。@mikalai:还有关于
BeginTransaction()的声明
只读操作不需要显式事务是完全错误的。即使在读操作中也使用显式事务被认为是良好的做法。请参阅。要回答以下问题:否,
Commit()在这种情况下,
是不必要的,因为OP已经使用了
using
来确保事务被正确处理,并且基础连接返回到连接池。
Commit()
不做任何
Dispose()
不做的只读操作。实际上,省略了
Commit()
这是一个好主意,因为这样可以确保在代码出现错误时不会意外写入任何更改,从而对实体进行意外更改。
Dispose()
在这种情况下会自动执行回滚。