【发布时间】:2011-10-13 07:17:07
【问题描述】:
为了这个例子,假设我必须为我国税收服务数据库的“人”实体建模,在我这个很小的国家,一个人的名字和姓氏就足够了以唯一标识此人。此外,税收服务的数据库不使用代理键,添加代理键将使该国未来 10 年的 GDP 归零。
Persons 表有三个字段:
- 名字
- 姓
- 当前地址
而且,考虑到我所在国家/地区的大小,该表对 FirstName、LastName> 列对具有 唯一 约束。
鉴于此架构,我非常简单的 Person 类具有以下成员:
- Key:PersonKey 类的实例,该类又具有 FirstName 和 LastName 成员,当然还实现了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 会执行以下操作:
- 打开记录集以仅加载 Persons 表中的关键属性(即仅加载 FirstName 和 LastName 字段);
- 对于从 Persons 加载的每个 FirstName、LastName> 对,它会发出一个 SELECT - 当然是针对 Persons em> - 为拥有 FirstName 和 LastName 的人加载 CurrentAddress。
换句话说,NHibernate 首先加载键,然后发出一系列 SELECT 来加载每个 Person 分别在 WHERE 子句中提供键。
如果我对写入数据库不感兴趣,有没有办法告诉 NHibernate 它可以使用单个记录集来检索 键和非表中的关键属性?
【问题讨论】:
-
更新:仅当我使用
IQuery.Enumerable()时才会发生这种情况。如果我使用IQuery.List()NHibernate 会做聪明的事情并且只查询表一次。但是,当我的表中有 3.7 亿人并且我的应用程序只需要一次处理一个人时,将所有人员存储在一个列表中是有点矫枉过正。 -
当你使用
IQuery.Future<Person>()时它的表现如何? -
感谢您的建议。
IQuery.Future<Person>()的行为因驱动程序的能力而异。如果我使用的驱动程序不支持多个查询,但支持多个结果集(例如 OdbcDriver),那么::Future()的运行方式与::List()完全相同。另一方面,如果驱动程序支持多个查询并且没有多个结果集(例如 SqlClientDriver),那么::Future()会读取内存中的整个记录集(杀死应用程序)。不幸的是,NHibernate 没有附带支持多查询和多记录集的 SQL Server 驱动程序。 -
更新:即使我有一个支持两者的驱动程序,
IQuery.Future<Person>()似乎会将所有结果加载到一个列表中。
标签: nhibernate composite-key composite-id