NHibernate应用 many-to-many

在数据库的多对多关系中, 实现方法是通过一个额外的关联表将两个主表关联起来,关联表中只保存两个主表的主健,显然, 主表与关联表是一对多的关系. 这样两个主表就通过这个关联表构成了一个多对多的关系.
典型的例子就是用户和权限了, 每个用户可以有多个权限, 而每个权限也可以分配给多个用户. 通过一个用户权限表就可以实现这样的要求.

因为关联表并没有其它任何信息, 所以在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对象时再载入, 这也算是延迟加载的一个变相实现吧.

<script src="http://www.cchensoft.com/gad/blog_csdn_article.js" type=text/javascript></script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值