- NHibernate 教程
- NHibernate - 首页
- NHibernate - 概述
- NHibernate - 架构
- NHibernate - ORM
- NHibernate - 环境设置
- NHibernate - 快速入门
- NHibernate - 基础ORM
- NHibernate - 基本CRUD操作
- NHibernate - 性能分析器
- 为映射文件添加IntelliSense
- NHibernate - 数据类型映射
- NHibernate - 配置
- NHibernate - 覆盖配置
- NHibernate - 批处理大小
- NHibernate - 缓存
- NHibernate - 组件映射
- NHibernate - 关系
- NHibernate - 集合映射
- NHibernate - 级联操作
- NHibernate - 延迟加载
- NHibernate - 反向关系
- NHibernate - Load/Get
- NHibernate - LINQ
- NHibernate - 查询语言 (HQL)
- NHibernate - Criteria 查询
- NHibernate - QueryOver 查询
- NHibernate - 原生SQL
- NHibernate - Fluent NHibernate
- NHibernate 有用资源
- NHibernate - 快速指南
- NHibernate - 有用资源
- NHibernate - 讨论
NHibernate - 集合映射
本章将介绍如何表示集合。NHibernate 中可以使用不同类型的集合,例如:
- 列表 (Lists)
- 集合 (Sets)
- 包 (Bags)
从 .NET 的角度来看,我们通常处理列表或非常简单的列表、字典等数据结构。.NET 没有各种各样的集合类型。那么,为什么 NHibernate 需要所有这些不同类型呢?这实际上与数据库有关。
列表 (List)
列表是有序的元素集合,这些元素不一定是唯一的。
我们可以使用IList <T> 来映射它。
因此,尽管我们通常可能有一个地址列表,并且从应用程序的角度来看,我们知道这些元素是唯一的,但列表中没有任何内容可以阻止我们向该列表中插入重复元素。
集合 (Set)
集合是唯一元素的无序集合。如果您尝试将两个重复的元素插入集合中,它将抛出异常。
NHibernate 中没有关于它的具体内容。
这只是拥有泛型集合实现的一种便捷方式。如果您使用的是 .NET 4,可以使用新的HashSet <T> 来表示这些,但在大多数 NHibernate 应用程序中,我们将其表示为 ISet。
它是无序的,如果您从数据库中提取地址列表或订单列表,除非您添加特定的 Order by 子句,否则您不知道它们的顺序。
因此,一般来说,您从数据库中提取的数据是集合。
它们是唯一元素的无序集合。
包 (Bag)
我们在数据库世界中看到的另一个常见集合是包,它与集合类似,只是它可以包含重复元素。
在 .NET 世界中,我们通过 IList 来表示它。
集合可能是最常见的,但是根据您的应用程序,您也会看到列表和包。让我们看一下上一章中定义了 Set 订单的customer.hbm.xml 文件。
<?xml version = "1.0" encoding = "utf-8" ?> <hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemo" namespace = "NHibernateDemo"> <class name = "Customer"> <id name = "Id"> <generator class = "guid.comb"/> </id> <property name = "FirstName"/> <property name = "LastName"/> <property name = "AverageRating"/> <property name = "Points"/> <property name = "HasGoldStatus"/> <property name = "MemberSince" type = "UtcDateTime"/> <property name = "CreditRating" type = "CustomerCreditRatingType"/> <component name = "Address"> <property name = "Street"/> <property name = "City"/> <property name = "Province"/> <property name = "Country"/> </component> <set name = "Orders" table = "`Order`"> <key column = "CustomerId"/> <one-to-many class = "Order"/> </set> </class> </hibernate-mapping>
如您所见,我们已将 orders 集合映射为一个集合。请记住,集合是唯一元素的无序集合。
现在,如果您查看 Customer 类,您会看到 Orders 属性是用 ISet 定义的,如下面的程序所示。
public virtual ISet<Order> Orders { get; set; }
现在运行此应用程序时,您将看到以下输出。
New Customer: John Doe (00000000-0000-0000-0000-000000000000) Points: 100 HasGoldStatus: True MemberSince: 1/1/2012 12:00:00 AM (Unspecified) CreditRating: Good AverageRating: 42.42424242 Orders: Order Id: 00000000-0000-0000-0000-000000000000 Order Id: 00000000-0000-0000-0000-000000000000 Reloaded: John Doe (1f248133-b50a-4ad7-9915-a5b8017d0ff1) Points: 100 HasGoldStatus: True MemberSince: 1/1/2012 12:00:00 AM (Utc) CreditRating: Good AverageRating: 42.4242 Orders: Order Id: c41af8f2-7124-42a7-91c5-a5b8017d0ff6 Order Id: 657f6bb0-1f42-45fc-8fc7-a5b8017d0ff7 The orders were ordered by: John Doe (1f248133-b50a-4ad7-9915-a5b8017d0ff1) Points: 100 HasGoldStatus: True MemberSince: 1/1/2012 12:00:00 AM (Utc) CreditRating: Good AverageRating: 42.4242 Orders: Order Id: c41af8f2-7124-42a7-91c5-a5b8017d0ff6 Order Id: 657f6bb0-1f42-45fc-8fc7-a5b8017d0ff7 John Doe (1f248133-b50a-4ad7-9915-a5b8017d0ff1) Points: 100 HasGoldStatus: True MemberSince: 1/1/2012 12:00:00 AM (Utc) CreditRating: Good AverageRating: 42.4242 Orders: Order Id: c41af8f2-7124-42a7-91c5-a5b8017d0ff6 Order Id: 657f6bb0-1f42-45fc-8fc7-a5b8017d0ff7 Press <ENTER> to exit...
如果集合中的项目不需要唯一,如果您可以在此集合中多次出现具有相同主键的多个订单,那么最好将其映射为包,如下面的程序所示。
<bag name = "Orders" table = "`Order`"> <key column = "CustomerId"/> <one-to-many class = "Order"/> </bag>
现在,如果您运行此应用程序,您将收到一个异常,因为如果我们查看 customer 类,您会注意到订单在 C# 代码中被标记为 ISet。
因此,我们还需要将其更改为 IList,然后在这里,我们需要将构造函数中的 HashSet 更改为 List。
public class Customer { public Customer() { MemberSince = DateTime.UtcNow; Orders = new List<Order>(); } public virtual Guid Id { get; set; } public virtual string FirstName { get; set; } public virtual string LastName { get; set; } public virtual double AverageRating { get; set; } public virtual int Points { get; set; } public virtual bool HasGoldStatus { get; set; } public virtual DateTime MemberSince { get; set; } public virtual CustomerCreditRating CreditRating { get; set; } public virtual Location Address { get; set; } public virtual IList<Order> Orders { get; set; } public virtual void AddOrder(Order order) { Orders.Add(order); order.Customer = this; } public override string ToString() { var result = new StringBuilder(); result.AppendFormat("{1} {2} ({0})\r\n\tPoints: {3}\r\n\tHasGoldStatus: {4}\r\n\tMemberSince: {5} ({7})\r\n\tCreditRating: {6}\r\n\tAverageRating: {8}\r\n", Id, FirstName, LastName, Points, HasGoldStatus, MemberSince, CreditRating, MemberSince.Kind, AverageRating); result.AppendLine("\tOrders:"); foreach(var order in Orders) { result.AppendLine("\t\t" + order); } return result.ToString(); } }
运行应用程序时,您将看到相同的行为。但是,现在我们可以让同一个集合中出现多个订单。
John Doe (00000000-0000-0000-0000-000000000000) Points: 100 HasGoldStatus: True MemberSince: 1/1/2012 12:00:00 AM (Unspecified) CreditRating: Good AverageRating: 42.42424242 Orders: Order Id: 00000000-0000-0000-0000-000000000000 Order Id: 00000000-0000-0000-0000-000000000000 Reloaded: John Doe (fbde48f5-d620-4d1c-9a7f-a5b8017c3280) Points: 100 HasGoldStatus: True MemberSince: 1/1/2012 12:00:00 AM (Utc) CreditRating: Good AverageRating: 42.4242 Orders: Order Id: 6dd7dbdb-354f-4c82-9c39-a5b8017c3286 Order Id: 9b3e2441-a81b-404d-9aed-a5b8017c3287 The orders were ordered by: John Doe (fbde48f5-d620-4d1c-9a7f-a5b8017c3280) Points: 100 HasGoldStatus: True MemberSince: 1/1/2012 12:00:00 AM (Utc) CreditRating: Good AverageRating: 42.4242 Orders: Order Id: 6dd7dbdb-354f-4c82-9c39-a5b8017c3286 Order Id: 9b3e2441-a81b-404d-9aed-a5b8017c3287 John Doe (fbde48f5-d620-4d1c-9a7f-a5b8017c3280) Points: 100 HasGoldStatus: True MemberSince: 1/1/2012 12:00:00 AM (Utc) CreditRating: Good AverageRating: 42.4242 Orders: Order Id: 6dd7dbdb-354f-4c82-9c39-a5b8017c3286 Order Id: 9b3e2441-a81b-404d-9aed-a5b8017c3287 Press <ENTER> to exit...