nHibernate - 复杂的多对多类映射

发布于 2024-09-14 04:26:41 字数 3431 浏览 0 评论 0原文

我是 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 应该是什么,而且我什至没有尝试将权限列表放入还在那里。

有人有什么想法吗?

任何帮助将不胜感激。 萨恩

I'm new to nhibernate, and I'm sorry if this is answered elsewhere, but I've been looking for the last couple of hours, and can't find a solution that works.

A bit of background:
I'm trying to write an Admin area where there are users and sites, and a user can have access to multiple sites - but at various permission levels for each site.

Ideally I would like my classes look like this.

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; }
   }
}

And my database schema looks like this

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))
}

And the hibernate mapping files currently look like:
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>

and Sites.hbm.xml is

<?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>

Individually the User, Permission and Site classes all map fine - but i just can't figure out what AdminUserSite should be, and I haven't even attempted to put the permissions list in there yet.

Does anyone have any ideas?

Any help would be very appreciated.
Saan

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

自由如风 2024-09-21 04:26:41

我认为您需要稍微研究一下数据库模式。我认为 AdminUserSite 表是你的问题。

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

实体:用户、权限、站点、SiteArea

接下来,计算出关系:

  • 1 User 有很多权限

  • 1 SiteArea 有很多权限

  • 1 个站点有很多 SiteArea

(希望我没看错:))

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

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

I think you need to work on the database schema a bit. I think the AdminUserSite table is your problem.

Firstly, work out your entities (these should be simple nouns, which is why AdminUserSite seems out of place to me).

Entities: User, Permission, Site, SiteArea

Next, work out the relationships:

  • 1 User has many Permissions

  • 1 SiteArea has many Permissions

  • 1 Site has many SiteAreas

(hope I got that right :) )

After that, your hbm and tables should flow more naturally.

Remember that normally you will have 1 table per entity, unless you have a many-many relationship (in which case you will need a joining table).

新人笑 2024-09-21 04:26:41

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

<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 会话加载/检索,则两个位置的对象将是相同的。
如果有逻辑(即直接方式和交叉关系方式),以两种方式访问​​一个对象就不是异端邪说。

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

Generally a relation table mapping look like this :

<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>

In that way you can access either Site or User by its relation object or load relation object by criteria based on Site or User.

By the way, if your Permission object contains reference to user and site you may not need the AdminUserSite relation, the permission mapping already do it.

Edit about your comment Kind of replicating the same information in two spots.

Since NHibernate -like all ORM- has a first level cache you don't have to matter if your object can be accessed in two ways. You just have to ensure that your mappings are usefull to optimize and design your application well.

In this case, it's not a 'replication' but a reference. The object will be the same in the two spots if loaded by/retrieved from the same NHibernate session.
Accessing an object in two ways if they have a logic (ie. direct way and cross-relation way) is not an heresy.

This is most a data layer work to achieve to provide right methods to access the right objects in the right way :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文