1

我们在 Oracle 中遇到了一个奇怪的问题。我将首先勾勒一些(简化的)上下文:

考虑这个到实体的映射:

public EntityMap()
{
    Table("EntityTable");
    Id(x => x.Id)
        .Column("entityID")
        .GeneratedBy.Native("ENTITYID").UnsavedValue(0);
    Map(x => x.SomeBoolean).Column("SomeBoolean");
}

这个代码:

var entity = new Entity();
using (var transaction = new TransactionScope(TransactionScopeOption.Required))
{
    Session.Save(entity);
    transaction.Complete();
}

//A lot of code
if(someCondition)
{            
    using (var transaction = new TransactionScope(TransactionScopeOption.Required))
    {
        enitity.SomeBoolean = true;
        Session.Update(entity);
        transaction.Complete();
    }
}

这段代码被调用了几次。它第一次生成以下查询:

select ENTITYID.nextval from dual
INSERT INTO Entity
    (SomeBoolean, EntityID)
    VALUES  (0, 1216)
UPDATE Entity
    SET SomeBoolean = 1
    WHERE  EntityID = 1216

第二次调用时会生成这些查询(someCondition为假)

select ENTITYID.nextval from dual
INSERT INTO Entity
    (SomeBoolean, EntityID)
    VALUES  (0, 1217)

现在麻烦开始了。从现在开始,每次插入都将使用正确的自动增量值,但更新将始终使用 1217

select ENTITYID.nextval from dual
INSERT INTO Entity
    (SomeBoolean, EntityID)
    VALUES  (0, 1218)
UPDATE Entity
    SET SomeBoolean = 1
    WHERE  EntityID = 1217

当然,这不是我们想要发生的。如果我在调试时检查 Id 的值,它包含正确的自动增量值。不知何故,在 NHibernate 的深处,不正确的被分配给了 WHERE 子句......

奇怪的是,这只发生在 Oracle 上。如果我将 NHibernate 切换到 MsSql,一切都会像魅力一样工作。

4

1 回答 1

0

所以我发现了发生了什么。NHibernate 更改了 1.x 和 2.x 版本之间的默认连接释放模式。不是在会话被释放时关闭连接,而是在每次事务后关闭连接。但是,我们手动协调我们的事务,这显然在 Oracle 中造成了麻烦。

这个问题有一些额外的信息,NHibernate 文档中的这个条目也阐明了如何处理连接:

从 NHibernate 开始,如果您的应用程序通过 System.Transactions 库等 .NET API 管理事务,ConnectionReleaseMode.AfterTransaction 可能会导致 NHibernate 在一个事务期间打开和关闭多个连接,从而导致不必要的开销和从本地到分布式的事务提升。指定 ConnectionReleaseMode.OnClose 将恢复为旧行为并防止发生此问题。

这篇博文让我找到了正确的方向。

于 2013-01-03T11:56:28.933 回答