【问题标题】:NHibernate executing a SELECT before every INSERTNHibernate 在每次 INSERT 之前执行 SELECT
【发布时间】:2013-11-08 22:28:34
【问题描述】:

我有一个只有一个字段 (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 在每个 INSERT 调用之前执行 SELECT 语句。像这样的:

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

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

【问题讨论】:

  • 使用 Id 创建实体将从数据库中获取它,因此这是预期的行为
  • “数据库”是什么对象类型?

标签: c# sql nhibernate


【解决方案1】:

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

  1. ID beeing 字符串 -> 具有生成器类型 assigned(问题中的 fluent-mapping 行)
  2. 虽然不鼓励,但使用了 session.SaveOrUpdate(e)

见:5.1.4.7. Assigned Identifiers,摘录:

由于其固有性质,使用此生成器的实体不能 通过 ISession 的 SaveOrUpdate() 方法保存。相反,你必须 明确指定 NHibernate 是否应该保存对象或 通过调用 Save() 或 Update() 方法更新 会话。

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

仅使用Save(e),在Database.Entities.Add(e) 后面,并且不会发出支持基础设施 SELECT。

【讨论】:

  • 非常感谢您,Radim!这完全有道理:如果我打电话给SaveOrUpdate,它需要先知道实体是否存在!我试过Save,效果很好;)
  • 如果有帮助的话就太好了。享受 NHibernate... 惊人的工具 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-24
  • 1970-01-01
相关资源
最近更新 更多