0

多対多の関係を持つ2つのテーブルがあります。ユーザーは多くのグループを持つことができ、グループは多くのユーザーを持つことができます。

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

Fluent NHibernateを使用して、次のようにそれらを自動マッピングします。

.Override<User>(obj => obj.HasManyToMany(x => x.Groups).Table("UserToGroup").Cascade.AllDeleteOrphan())

その結果、Nhibernateは3つのテーブルを生成します。1。ユーザー-マップされたオブジェクトテーブル2.グループマップされたオブジェクトテーブル3.UserToGroup-生成された関連付けテーブル

要件は、これらのテーブルに次の機能があることです。1. AddUser(UInt64 UserId、IEnumerable groups)2. RemoveGroup(GroupGuid groupGuild)3. Dictionary> GetGroupToUsers();

AddUserメソッドは正常に機能しています。すべてのテーブルが更新されました。OK:*ユーザーテーブルに新しいユーザーを挿入します。OK*グループテーブルに新しいグループを挿入します。OK*UserToGroupテーブルに新しいリレーションレコードを挿入します。わかった

次のコードを使用して、ユーザー(グループを含む)を追加します。

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

次のコードを使用してグループを削除します。

public void RemoveGroup(GroupGuid groupGuild)
{
     IList<Group> groupsToRemove = Session.QueryOver<Group>().Where(
            row => row.GroupGuid == groupGuild).List();
     foreach (Group group in groupsToRemove)
     {
          group.Users.Clear();
          Session.Delete(group);
     }
}

RemoveGroupメソッドは、次の例外で失敗しました。

threw exception: 
NHibernate.Exceptions.GenericADOException: could not delete: [StorageObject.Group#11111111-1111-1111-1111-111111111111][SQL: DELETE FROM "Group" WHERE Id = ?] ---> System.Data.SqlServerCe.SqlCeException: The primary key value cannot be deleted because references to this key still exist. [ Foreign key constraint name = FK4B29424018FA0CD4 ]

参照UserToGroupテーブルがGroupテーブルを指しているため、Groupテーブルを削除できないことを理解しています。

  1. 最初の質問:このmanyToMany関係を両側から制御できるようにしたいことを理解するために休止状態にする方法:ユーザー側からグループを持つユーザーを追加します。そして、グループを削除します-グループ側から

InverseをUserテーブルに移動しようとしましたが、この場合、Userを追加すると、関連付けテーブルにデータが入力されません。

この種のmanyToMany関係を定義する最良の方法は何ですか?

更新:私が試したもう1つの方法は、この構成のグループにもユーザーのリストを含めることです。removeGroupは機能していませんが、addUserは特定のシナリオでは機能しません。

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

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

今、私は双方向の多対多を持っています。私のFluentマッピングは次のとおりです。

.Override<User>(obj => obj.HasManyToMany(x => x.Groups).ParentKeyColumn("UserId").ChildKeyColumn("GroupId").Table("UserToGroup").Cascade.SaveUpdate()
.Override<Group>(obj => obj.HasManyToMany(x => x.Users).ParentKeyColumn("GroupId").ChildKeyColumn("UserId").Table("UserToGroup")

この構成を使用すると、RemoveGroupは正常に機能しますが、次の場合はAddUserが機能しません。同じグループを含む2人のユーザーを追加する場合、関連付けテーブルは最初のリレーションを削除し、両方のリレーションではなく最後の参照のみを保持します。お知らせ下さい。

4

1 に答える 1

1

グループに逆コレクションを追加してみてください。

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

マッピング:

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

あなたのRemoveメソッド:

public void RemoveGroup(GroupGuid groupGuild)
{
     IList<Group> groupsToRemove = Session.QueryOver<Group>().Where(
            row => row.GroupGuid == groupGuild).List();
     foreach (Group group in groupsToRemove)
     {
          group.Users.Clear();   // Removes references from all users pointing to that group
          Session.Delete(group);
     }
}

トランザクションをコミットすると、参照は自動的に削除されます。私はこれを自分で試したことはありませんが、うまくいくかもしれません。

于 2012-06-13T17:30:30.853 に答える