nHibernate - 复杂的多对多类映射

时间:2010-08-12 07:34:38

标签: nhibernate class nhibernate-mapping many-to-many

我是nhibernate的新手,如果在其他地方得到解答,我很抱歉,但我一直在寻找最近几个小时,但找不到有效的解决方案。

一些背景知识: 我正在尝试编写一个管理区域,其中有用户和站点,用户可以访问多个站点 - 但每个站点具有不同的权限级别。

理想情况下,我希望我的课程看起来像这样。

namespace MyApp.Users
{
   public class User
   {
      public virtual int Id { get; set; }
      public virtual string Name { get; set; }
      public virtual string Password { get; set; }
      public virtual IList<AdminUserSite> Sites { get; set; }
   }

   public class AdminUserSite
   {
      public virtual int UserTypeId { get; set; }
      public virtual Site AdminSite { get; set; }
      public virtual IList<Permission> Permissions { get; set; }
   }

   public class Permission
   {
      public virtual int Id { get; set; }
      public virtual int AreaID { get; set; }
      public virtual bool CanView { get; set }
      public virtual bool CanEdit { get; set }
   }
}

namespace MyApp.Sites
{
   public class Site
   {
      public virtual int Id { get; set; }
      public virtual string Title { get; set; }
   }
}

我的数据库架构看起来像这样

f_user
{
   f_user_id (int, PK)
   name (nvarchar(50))
   password (nvarchar(25))
}

f_user_site
{
   f_user_id (int, PK)
   f_site_id (int, PK)
   d_user_type_id (int)
}

f_perm
{
   f_perm_id (int, PK)
   f_site_id (int)
   f_user_id (int)
   d_area_id (int)
   can_read (bit)
   can_write (bit)
}

f_site
{
   f_site_id (int, PK)
   title (nvarchar(50))
}

hibernate映射文件目前看起来像: Users.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
   assembly="MyApp"
   namespace="MyApp.Users"
   default-lazy="true">

   <class name="User" table="f_user">
      <id name="Id" column="f_user_id">
         <generator class="identity" />
      </id>
      <property name="Name" column="name" />
      <property name="Password" column="password" />

      <bag name="Sites" table="f_user_site" inverse="true" cascade="all-delete-orphan">
         <key column="f_user_id"/>
         <one-to-many class="AdminUserSite"/>
      </bag>
   </class>

   <class name="Permission" table="f_perm">
      <id name="Id" column="f_perm_id">
         <generator class="identity" />
      </id>
      <property name="AreaId" column="d_area_id" />
      <property name="CanView" column="can_read" />
      <property name="CanEdit" column="can_write" />
   </class>

   <class name="AdminUserSite" table="f_user_site">
      <property name="UserTypeId" column="d_user_type_id" />
      <many-to-one name="Site" class="MyApp.Sites.Site, MyApp.Sites" foreign-key="f_site_id"></many-to-one>
   </class>

</hibernate-mapping>

和Sites.hbm.xml是

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
   assembly="MyApp"
   namespace="MyApp.Sites"
   default-lazy="true">

   <class name="Site" table="f_site">
      <id name="Id" column="f_site_id">
         <generator class="identity" />
      </id>
      <property name="Title" column="title" />
   </class>

</hibernate-mapping>

单独地,用户,权限和站点类都可以正常映射 - 但我无法弄清楚AdminUserSite应该是什么,我甚至还没有尝试将权限列表放在那里。

有没有人有任何想法?

非常感谢任何帮助。 Saan

2 个答案:

答案 0 :(得分:0)

我认为您需要对数据库架构进行一些处理。我认为AdminUserSite表是你的问题。

首先,找出你的实体(这些应该是简单的名词,这就是为什么AdminUserSite对我来说不合适的原因。)

实体:用户,权限,网站,SiteArea

接下来,找出关系:

  • 1用户有很多权限

  • 1 SiteArea有许多权限

  • 1网站有很多SiteAreas

(希望我说得对:))

之后,你的hbm和表应该更自然地流动。

请记住,通常每个实体都有1个表,除非你有很多关系(在这种情况下你需要一个连接表)。

答案 1 :(得分:0)

通常,关系表映射如下所示:

<class name="AdminUserSite" table="f_user_site">
  <composite-id >
    <key-many-to-one name="Site" column="f_site_id" class="Site" />
    <key-many-to-one name="User" column="f_user_id" class="User"/>
  </composite-id>

</class>

通过这种方式,您可以通过其关系对象访问站点或用户,或者按照基于站点或用户的条件加载关系对象。

顺便说一下,如果你的Permission对象包含对用户和站点的引用,你可能不需要AdminUserSite关系,那么权限映射已经完成了。

关于您的评论

编辑 在两个位置复制相同信息的种类。

由于NHibernate类似所有ORM-都具有第一级缓存,因此如果可以通过两种方式访问​​对象,则无需担心。您只需确保映射对于优化和设计应用程序非常有用。

在这种情况下,它不是'复制'而是参考。如果从同一个NHibernate会话加载/检索,则该对象在两个点中是相同的。 如果对象具有逻辑(即直接方式和交叉关系方式),则以两种方式访问​​对象并不是异端。

这是大多数数据层工作,以提供正确方法以正确的方式访问正确的对象:)