【问题标题】:NHibernate issues redundant queries with composite keysNHibernate 使用复合键发出冗余查询
【发布时间】:2011-10-13 07:17:07
【问题描述】:

为了这个例子,假设我必须为我国税收服务数据库的“人”实体建模,在我这个很小的国家,一个人的名字和姓氏就足够了以唯一标识此人。此外,税收服务的数据库不使用代理键,添加代理键将使该国未来 10 年的 GDP 归零。

Persons 表有三个字段:

  • 名字
  • 当前地址

而且,考虑到我所在国家/地区的大小,该表对 FirstName、LastName> 列对具有 唯一 约束。

鉴于此架构,我非常简单的 Person 类具有以下成员:

  • KeyPersonKey 类的实例,该类又具有 FirstNameLastName 成员,当然还实现了Equals()GetHashCode();
  • CurrentAddress:一个简单的字符串。

NHibernate 映射如下所示:

<class name="Person" table="Persons" lazy="false">    

  <composite-id name="Key" class="PersonKey">
    <key-property name="FirstName" type="string" column="FirstName"/>
    <key-property name="LastName" type="string" column="LastName"/>
  </composite-id>

  <property name="CurrentAddress" type="string" column="CurrentAddress" not-null="true" />

</class>

到目前为止一切顺利,这个映射工作正常,我可以愉快地从数据库中加载 Person 实体。

但是,当我深入了解时,我可以看到在加载整个人员集时,NHibernate 会执行以下操作:

  1. 打开记录集以仅加载 Persons 表中的关键属性(即仅加载 FirstNameLastName 字段);
  2. 对于从 Persons 加载的每个 FirstName、LastName> 对,它会发出一个 SELECT - 当然是针对 Persons em> - 为拥有 FirstNameLastName 的人加载 CurrentAddress。

换句话说,NHibernate 首先加载键,然后发出一系列 SELECT 来加载每个 Person 分别在 WHERE 子句中提供键。

如果我对写入数据库不感兴趣,有没有办法告诉 NHibernate 它可以使用单个记录集来检索 键和非表中的关键属性?

【问题讨论】:

  • 更新:仅当我使用 IQuery.Enumerable() 时才会发生这种情况。如果我使用IQuery.List() NHibernate 会做聪明的事情并且只查询表一次。但是,当我的表中有 3.7 亿人并且我的应用程序只需要一次处理一个人时,将所有人员存储在一个列表中是有点矫枉过正。
  • 当你使用IQuery.Future&lt;Person&gt;()时它的表现如何?
  • 感谢您的建议。 IQuery.Future&lt;Person&gt;() 的行为因驱动程序的能力而异。如果我使用的驱动程序不支持多个查询,但支持多个结果集(例如 OdbcDriver),那么::Future() 的运行方式与::List() 完全相同。另一方面,如果驱动程序支持多个查询并且没有多个结果集(例如 SqlClientDriver),那么::Future() 会读取内存中的整个记录​​集(杀死应用程序)。不幸的是,NHibernate 没有附带支持多查询和多记录集的 SQL Server 驱动程序。
  • 更新:即使我有一个支持两者的驱动程序,IQuery.Future&lt;Person&gt;() 似乎会将所有结果加载到一个列表中。

标签: nhibernate composite-key composite-id


【解决方案1】:

IQuery.Enumerable 具有您在评论中提到的行为(首先加载键,MoveNext 上的元素)

在任何情况下,NH 都不是为您尝试创建的大规模处理场景而设计的。

使用原始 DataReader 可以获得更好的性能。

【讨论】:

  • 感谢 Diego,这就是我所担心的,也是迄今为止我一直在怀疑的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-13
  • 2019-01-23
  • 2016-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多