1

我有一个只有一个字段 ( Value) 和以下映射的实体:

Id(x => x.Value).Column("value").Length(150);

当我执行以下代码时

using (var tx = Database.BeginTransaction())
{
    for (int i = 0; i < 10; i++)
    {
        var e = new Entity { Id = "Value" + i };
        Database.Entities.Add(e);
    }
    tx.Commit();
}

NHibernate在每次调用SELECT之前执行一个语句。INSERT像这样的东西:

NHibernate: SELECT * FROM entity entity_ WHERE entity_.value=@p0; @p0 = 'Value0'
NHibernate: INSERT INTO entity ...
NHibernate: SELECT * FROM entity entity_ WHERE entity_.value=@p0; @p0 = 'Value1'
NHibernate: INSERT INTO entity ...
NHibernate: SELECT * FROM entity entity_ WHERE entity_.value=@p0; @p0 = 'Value2'
NHibernate: INSERT INTO entity ...

如果我启用批量模式(设置adonet.batch_size),它首先执行所有SELECT语句,然后是INSERT批量模式的语句。

这是预期的行为吗?如果是这样,我应该怎么做才能避免这种情况?

4

1 回答 1

2

这种行为是正确的,与以下事实有关:

  1. ID beeeing 字符串 ->分配了生成器类型(问题中的 fluent-mapping 行)
  2. 虽然气馁,但session.SaveOrUpdate(e)被使用

见:5.1.4.7。分配的标识符,提取:

由于其固有的性质,使用此生成器的实体无法通过 ISession 的 SaveOrUpdate() 方法保存。相反,您必须通过调用 ISession 的 Save() 或 Update() 方法来显式指定 NHibernate 是否应该保存或更新对象。

在这种情况下,NHibernate 几乎是绝望的。为什么?因为无法保证分配的 id ('value1', 'value2'..) 是否已经在 DB 中。因此,要确定是否应该发出INSERTUPDATE ,它必须询问 DB。这就是为什么 SELECT 在那个决定之前。

使用Save(e)唯一的、后面的Database.Entities.Add(e)和不支持基础设施的SELECT 会发出。

于 2013-11-09T10:48:35.550 回答