NHibernate:实现多对多关系

3

我有两张表,它们之间是多对多的关系。

public class User
{
   public virtual Guid Id { get; set; }
   public virtual UInt64 UserId { get; set; }
   public virtual IList<Group> Groups{ get; set; }
}

public class Group
{
   public virtual Guid Id { get; set; }
   public virtual Guid GroupGuid  { get; set; }
   public virtual IList<User> Users{ get; set; }
}

我使用Fluent NHibernate进行以下自动映射:
.Override<User>(obj => obj.HasManyToMany(x => x.Groups).Table("UserToGroup").Cascade.AllDeleteOrphan())

.Override<Group>(obj => obj.HasManyToMany(x => x.Users).Table("UserToGroup").Cascade.AllDeleteOrphan().Inverse())

当我添加一个包含组列表的用户时,所有表都更新成功: 在User表中插入新用户。OK 在Group表中插入新组。OK 在UserToGroup表中插入新关系。OK
我使用以下代码添加用户(包括组):
public void AddUser(User userData, IList<Guid> groupIds)
{
   User user = new User();
   user.UserId = userData.UserId;

   IList<User> Users = new List<Users();
   Users.Add(user);

   IList<Group> groups = new List<Group>();

   foreach (Guid groupId in groupIds)
   {
      Group grp = new Group();
      grp.GroupGuid = groupId;
      grp.Users = Users;
      groups.Add(grp);
   }

   user.Groups = groups;
   Session.Save(user);
}

问题: 当我添加一个包含已经存在于Group表中的GroupGuid的新用户时,会在Group表中插入一个具有相同GroupGuid和新ID的新记录。
问题:
1.如何使NHibernate仅向Group表添加新的GroupGuid id?并仍然在UserToGroup表中添加一个关系,将新用户与现有组相关联。
2.在AddUser方法中,我应该设置实体的两个方面吗?即设置user.Groups为group列表,并设置group.Users为user列表?
谢谢, Haimon。

你能展示一下你填充用户组的代码吗? - Martin Ernst
@MartinErnst 在 "我使用以下代码添加用户(包括组):"之后,您可以在代码中看到组的人口数量。 - Haimon
1个回答

2
您遇到这个问题的原因可能是您在将组实体与用户对象关联时使用了未关联的组实体。所以您需要从数据库中加载它们。
或者,您可以切换到使用Guid作为实体的标识,而不是您设置的任何其他主键。
回答您的第二个问题,您只需要设置关系的一侧即可。但是,我对为什么您会有两个单独的关系表感到困惑。通常您只需要一个其他表:
User
Group
UserGroup

通过说我需要从数据库加载,您的意思是我应该使用Session.Load来加载我想要添加到用户的所有groupIds吗?如果groupId属性不是我的表ID,我该怎么做?关于切换到使用GroupGuid作为我的ID,我不能使用它,因为它的值不是由Hibernate设置的,而是由应用程序获取的(我无法使用Hibernate生成此属性)。关于您的最后一部分:我仅使用一个表来处理2个实体之间的关系。UserGroup是User和Group之间的关系表。 - Haimon
  1. 我不明白如何从数据库中加载组实体?(使用Session.Load/QueryOver?)
  2. 关于使用Guid - 目前我使用Guid Id(它是Id和PK,并由Hibernate生成),我还有一个名为GroupGuid的Guid属性,它是由应用程序获取的(不是PK也不是Id,也不是由Hibernate生成,而是由应用程序提供)。你所说的切换到Guid是什么意思 - 我已经使用了Guid(GroupGuid)。如果你的意思是让我只使用GroupGuid并将其作为表ID和PK - 那么我该如何做才能不让Hibernate为我生成它?
- Haimon
1
  1. 是的,您可以使用它们与Session.Load或某种查询一起使用。
  2. 您可以将其用作生成器类型http://nhforge.org/doc/nh/en/index.html#mapping-declaration-id-assigned,并依靠您的应用程序分配ID。
- Vadim
感谢您的回答。它通过在构造函数中将Group实体的Id设置为GroupGuid值来工作。并通过设置Id为generated.assign(现在我有两个具有相同值的列)。由于GroupGuid是Group Entity中组件中的属性,因此我无法将GroupGuid设置为实体Id。您知道在AutoMap中是否可以设置实体组件中的属性Id吗? - Haimon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接