在数据库的多对多关系中, 实现方法是通过一个额外的关联表将两个主表关联起来,关联表中只保存两个主表的主健,显然, 主表与关联表是一对多的关系. 这样两个主表就通过这个关联表构成了一个多对多的关系. 
典型的例子就是用户和权限了, 每个用户可以有多个权限, 而每个权限也可以分配给多个用户. 通过一个用户权限表就可以实现这样的要求. 
因为关联表并没有其它任何信息, 所以在NH中它不能算是一个持久对象, 没必要像处理one-to-many的情况那样.在NH中, 通过值集合映射来处理这种情况. 
下面以用户/权限为例再看看实际的处理情况. 
测试代码 
[Test] 
public void TestUserPermission() { 
User u = new User(); 
u.Name = "test name"; 
u.Password = "test password"; 
u.AddPermission( 10 ); 
session.Save(u); 
session.Close(); 
User u2 = session.Load( typeof(User), u.UserId ); 
Assertion.AssertNotNull( "add permission fail!", u2.Permissions[ 10 ] ); 
u2.AddPermission( 20 ); 
u2.RemovePermission( 10 ); 
session.Save(u2); 
session.Close(); 
User u3 = session.Load( typeof(User), u.UserId ); 
Assertion.AssertNull( "remove permission fail!", u3.Permission[ 10 ] ); 
Assertion.AssertNotNull( "add permission fail!", u3.Permission[ 20 ] ); 
} 
以上测试代码中session的相关操作请查看相关文档。 
在这里给User类定义了两个操作权限的方法: AddPermission和RemovePermission. 
类定义 
public class User { 
public User() { 
} 
public void AddPermission( int permissionId ) { 
permissions[ permissionId ] = dummyObject; 
} 
public void RemovePermission( int permissionId ) { 
permissions.Remove( permissionId ); 
} 
#region O/R Mapping Fields. 
private int userId; 
public int UserId 
{ 
get { return userId; } 
set { userId = value; } 
} 
private string name; 
public string Name 
{ 
get { return name; } 
set { name = value; } 
} 
private string password; 
public string Password 
{ 
get { return password; } 
set { password = value; } 
} 
private IDictionary permissions = new Hashtable(); 
public IDictionary Permissions 
{ 
get { return permissions; } 
set { permissions = value; } 
} 
#endregion 
private readonly object dummyObject = new object(); 
} 
在User类中,定义了一个Permissions集合用来保存用户的权限. 因为使用了IDictionary, 所以也定义了一个哑对象. 
映射文件 
<class name="User, AssemblyName " table="Users"> 
<id name="UserId" column="user_id" type="Int32" unsaved-value="0"> 
<generator class="identity"/> 
</id> 
<property name="Name" column="name" type="String"/> 
<property name="Password" column="password" type="String"/> 
<set name="Permissions" table="UserPermissions"> 
<key column="user_id"/> 
<element column="permission_id" type="Int32"/> 
</set> 
</class> 
在set定义中, 指定值集合的名称,以及关联表的名称, 再指定key值, 也即在关联表的健, 一般是主健. 
element元素指定产生值集合的列和类型. 
值集合的开销远小于对象集合的开销, 在有些时候, 可以考虑将one-to-many简化为集集合, 这样我们只取得many的id值, 在需要访问many对象时再载入, 这也算是延迟加载的一个变相实现吧.