更新使用Oracle上以前自动生成的ID

时间:2013-01-02 14:48:31

标签: sql-server oracle nhibernate

我们在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为false)

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,一切都像魅力一样。

1 个答案:

答案 0 :(得分:0)

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

This问题有一些额外的信息,this entry in the NHibernate documentation也说明了连接是如何处理的:

  

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

This blog post让我朝着正确的方向前进。