NHibernate中的列表vs集合vs包


109

NHibernate映射文件中的列表,集合和包之间有什么区别?它们与.NET集合有何关系?

Answers:


230

NHibernate语义:

  1. 列表:实体的有序集合,允许重复。IList在代码中使用.NET 。索引列将需要在NHibernate中进行映射。

  2. 设置:唯一实体的无序集合,不允许重复。使用Iesi.Collection.ISet在代码(NH V4之前)或System.Collections.Generic.ISet(NH V4 +)。覆盖GetHashCodeEquals指出重复项的业务定义很重要。可以通过定义orderby或通过定义比较器对SortedSet结果进行排序。

  3. 袋:实体的无序列表,允许重复。ICollection<T>在代码中使用.NET 。列表的索引列未映射,NHibernate不认可。


回复:#2,我们不能只使用常规ISet而不是Iesi
谢尔盖·塔切诺夫'16

@SergeyTachenov:请参阅stackoverflow.com/questions/9222058/…以获取可能的答案。撰写此答案时,ISet不是.net的一部分
Michael Gattuso

自NHibernate 4以来,对该问题最不受欢迎的答案是肯定的。因此也许也需要对此问题进行编辑。
谢尔盖·塔切诺夫'16

21

NHibernate中的所有这些对象与这些抽象数据类型(ADT)的其他实现完全相同。由于名称在其他事物上的通用性,我惊讶地发现在网上很难找到Sets and Bags,所以在这里列出了一些链接和说明。

有关更多详细信息,请查看以下内容: 清单套装袋子

一般规则是:

默认情况下,列表是有序的,如果您希望能够通过对象的索引拉出对象,或者对for循环有一种怪异的循环,则可以使用这些列表foreach。您不需要像访问“ 链表”中那样按顺序访问它们。此ADT允许重复。

请注意!尽管列表按BryanD的回答中的顺序进行排序,但是除非您通过命令指定顺序,否则绝对没有什么说它必须与您在执行HQL查询时从数据库中期望的顺序一致。正因为如此,有些人喜欢使用Set或Bags,因此不会给人以被订购的幻想。尽管我这么说,但大多数情况下它们会以可见的顺序出现,因为它们是按照在NHibernate运行的查询中找到的顺序添加到列表中的。

设置不是默认排序,你不能直接通过索引访问任何变量。默认情况下,集合是以上三个中唯一保持其对象唯一性的ADT。如果您要求不包含重复项,那么如果您有一个馆藏,这些效果很好。

正如您从上面的链接中看到的那样,Bags(或Multisets)是一种Set类型,它确实允许其中的对象与其他对象重复。这些通常不使用,因为可以忽略列表排序,因此将其视为袋。

关于它们在NHibernate中的使用方式,根据您在此处选择的ADT,没有从数据库中提取任何内容的不同,正是您要使用它的原因,因此您应该选择不同的ADT。

就我个人而言,我将Sets用于大多数事情,因为我通常要求子对象是唯一的,并且排序不是问题。尽管我将使用列表,其中我有一组对象,这些对象要按某种顺序排序(例如,时间)以实现此顺序,但我需要在HQL查询中手动设置“ order by”。


2
列表中的更正-在NHibernate映射文件中使用列表将需要映射索引列。这样,名单将在它被放置在正确的顺序被拉出。
迈克尔·加图索

@Michael Gattuso好点,我应该在上面的回答中提到我在谈论HQL查询(因此使用“ order by”注释),而不是映射文件中的实际集合规范。
杰伊,

使用bag的好处之一是,当您向数据库中添加新元素时,不必从数据库中加载它们。没有要检查的重复项,没有要确定的命令。
tvaananen 2014年

1

好吧,主要的区别是列表对元素具有隐式排序,并通过元素在列表中的位置进行索引。套装和袋子通常也可以由比较器或order by子句“排序”,当这些项目从数据库中出来时应用。就个人而言,我从来没有使用过Bags ...如果我知道要顺序排序的数据,则使用List,否则使用Set。


0

设置不允许您包含重复的元素。如果您尝试添加一些新元素,它将比较(使用equals方法)已在集合中的每个元素与您添加的元素,并且如果一个返回真,则不会添加元素

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.