【问题标题】:Nhibernate mapping - User and FriendsNhibernate 映射 - 用户和朋友
【发布时间】:2012-07-20 13:54:43
【问题描述】:

我正在尝试使用 Nhibernate 作为我的 ORM 的社交网络类型场景。

我有一个 User 表和一个 Friend 表。

User Table
----------
UserID
FirstName
LastName
Email

Friend Table
-------------
UserID
FriendUserID
AddedDateTime

这意味着在 Friend Table 中它可能有许多记录,例如

A - B (A initiated a friend request to B, accepted)
A - C (A initiated a friend request to C, accepted)
B - C
D - A (D initiated a friend request to A, accepted)
B - E

我怎样才能拥有一个 Nhibernate 属性,这样如果我为 A 调用 userObject.Friends,我将 B、C 和 D 作为用户对象返回。

为用户对象映射 xml...

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="Namespace.Data.Entities.User,Namespace.Data.Entities" table="`User`" lazy="true">
    <id name="UserId" column="`UserId`" type="Guid">
      <generator class="assigned" />
    </id>
    <property type="string" length="150" name="FirstName" column="`FirstName`" />
    <property type="string" length="150" name="LastName" column="`LastName`" />
    <property type="string" not-null="true" length="256" name="Email" column="`Email`" />    
    <bag name="UsersFriends" inverse="true" lazy="true" cascade="all">
      <key column="`UserID`" />
      <one-to-many class="Namespace.Data.Entities.Friend,Namespace.Data.Entities" />
    </bag>
    <bag name="FriendsofUser" inverse="true" lazy="true" cascade="all">
      <key column="`FriendUserID`" />
      <one-to-many class="Namespace.Data.Entities.Friend,Namespace.Data.Entities" />
    </bag>
  </class>
</hibernate-mapping>

和朋友对象...

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="Namespace.Data.Entities.Friend,Namespace.Data.Entities" table="`Friend`" lazy="true">
    <id name="Id" column="`ID`" type="int">
      <generator class="native" />
    </id>
    <property type="DateTime" not-null="true" name="AddedDateTime" column="`AddedDateTime`" />
    <many-to-one name="User" cascade="none" column="`UserID`" not-null="true" />
    <many-to-one name="FriendUser" cascade="none" column="`FriendUserID`" not-null="true" />
  </class>
</hibernate-mapping>

【问题讨论】:

  • 我认为递归关系更适合这里(用户有一个或多个用户作为朋友)
  • 您需要向我们展示您如何将 User 对象连接到 Friend 对象。请发布您的课程和映射。

标签: c# nhibernate nhibernate-mapping


【解决方案1】:

我建议

public class User
{
    public virtual long Id { get; set; }
    public virtual ICollection<FriendshipRequest> InitiatedRequests { get; private set; }
    public virtual ICollection<FriendshipRequest> ReceivedRequests { get; private set; }
    public virtual IEnumerable<User> Friends
    {
        get {
            return  (from fr in InitiatedRequests
                     where fr.Accepted
                     select fr.Friend)
                    .Concat(
                     from fr in ReceivedRequests
                     where fr.Accepted
                     select fr.Initiator);
        }
    }

    public User()
    {
        InitiatedRequests = new HashSet<FriendshipRequest>();
        ReceivedRequests = new HashSet<FriendshipRequest>();
    }
}

public class FriendshipRequest
{
    public virtual User Initiator { get; set; }
    public virtual User Friend { get; set; }
    public virtual bool Accepted { get { return Added != default(DateTime); } }
    public virtual DateTime Added { get; set; }

    // override Equals
}

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="Namespace.Data.Entities.User,Namespace.Data.Entities" table="`User`">
    ...
    <set name="InitiatedRequests" cascade="all" table="FriendshipRequests">
      <key column="`UserID`" />
      <composite-element>
        <property type="DateTime" name="Added" column="`AddedDateTime`" />
        <parent name="Initiator" />
        <many-to-one name="Friend" column="`FriendUserID`" not-null="true" />
      </composite-element>
    </bag>
    <set name="ReceivedRequests" cascade="all" table="FriendshipRequests" inverse="true">
      <key column="`FriendUserID`" />
      <composite-element>
        <property type="DateTime" name="Added" column="`AddedDateTime`" />
        <parent name="Friend" />
        <many-to-one name="Initiator" column="`UserID`" not-null="true" />
      </composite-element>
    </bag>
  </class>
</hibernate-mapping>
  • 对于 ReceivedRequests 集合,反向必须设置为 true,以便仅从一侧处理此集合
  • 我会设置,所以每个友谊只能添加一次(哪些属性是唯一的取决于 equals),这是有道理的,NHibernate 可以优化一些东西
  • 为避免选择 n+1,如果您打算使用好友集合,请确保您也渴望加载其他集合

【讨论】:

    猜你喜欢
    • 2010-09-28
    • 2015-09-11
    • 2011-05-28
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    相关资源
    最近更新 更多