NHibernate 使用复合键发出冗余查询
为了举例,假设我必须对我国税收服务数据库的“人”实体进行建模,并且在我的非常小的国家中,一个人的名字和姓氏足以唯一地标识这个人。此外,税收服务的数据库不使用代理键,向其中添加代理键将使该国未来 10 年的 GDP 归零。
Persons 表包含三个字段:
- FirstName
- LastName
- CurrentAddress
并且,考虑到我国的面积,该表具有对<FirstName、LastName>的唯一约束一对列。
鉴于此架构,我非常简单的 Person 类具有以下成员:
- Key:PersonKey 类的实例,该类又具有 Key >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 会执行以下操作:
- 打开记录集以仅加载关键属性(即仅 FirstName 和 LastName 字段)来自 Persons 表;
- 对于每个<FirstName、LastName>从 Persons 加载的对,它发出一个 SELECT - 当然也针对 Persons - 加载具有 FirstName 和 FirstName 的人的 CurrentAddress em>姓氏。
换句话说,NHibernate 首先加载键,然后发出一系列 SELECT 来分别加载每个 Person,并在 WHERE 子句中提供键。
假设我对写入数据库不感兴趣,有没有办法告诉NHibernate它可以使用单个记录集来检索两者键和非键属性桌子?
For the sake of the example, let's say that I have to model the "person" entity of the database of my country's revenue service, and that in my very small country the first name and the last name of a person are enough to uniquely identify the person. Additionally, the revenue service's database does not use surrogate keys, and adding a surrogate key to it would zero out the GDP of the country for the next 10 years.
The Persons table has three fields:
- FirstName
- LastName
- CurrentAddress
And, given the size of my country, the table has a unique constraint on the <FirstName, LastName> pair of columns.
Given this schema, my very simple Person class has the following members:
- Key: an instance of a PersonKey class, which in turn has FirstName and LastName members, and of course implements Equals() and GetHashCode();
- CurrentAddress: a simple string.
The NHibernate mapping looks as follows:
<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>
So far so good, this mapping works fine and I can happily load Person entities from the DB.
However, when I look under the hood, I can see that when loading the entire set of persons, NHibernate does the following:
- Opens a recordset to load key properties only (i.e. exclusively the FirstName and LastName fields) from the Persons table;
- For each <FirstName, LastName> pair loaded from Persons, it issues a SELECT - of course against Persons as well - to load the CurrentAddress for the person having that FirstName and LastName.
In other words, NHibernate is first loading the keys, and then it issues a series of SELECT's to load each Person separately providing the key in the WHERE clause.
Provided that I am not interested in writing to the database, is there a way to tell NHibernate that it could use a single recordset to retrieve both key and non-key properties from the table?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
IQuery.Enumerable
具有您在评论中提到的行为(首先加载键,然后加载 MoveNext 上的元素)无论如何,NH 都不是为您尝试创建的批量处理场景而设计的。
通过使用原始 DataReader,您将获得更好的性能。
IQuery.Enumerable
has the behavior you mentioned in your comment (loads the keys first, the elements on MoveNext)In any case, NH is not designed for the mass-processing scenario you are trying to create.
You'll have much better performance by using a raw DataReader.