-->

NHibernate many-to-many relationship question: can

2020-07-30 02:41发布

问题:

Each user has a list of roles:

  <class name="User" lazy="false" table="Users">
    <id name="Id" type="int">
      <generator class="native"/>
    </id>

    <property name="Name" />

    <bag name="RoleList" table="User_Role" inverse="true" lazy="false" collection-type="Roles">
      <key column="UserId" foreign-key="Id"/>
      <many-to-many class="Role" column="RoleId"/>
    </bag>

  </class>

I am tracking all the queries to the SQL server. When I select user, I also see the SQL SELECT statement (which is Ok). The problem is when I am trying to update an existing user (that has roles): I see only an update to User table, but not to User_Role (which is bad).

To clarify: I don't expect inserts/updates in Role table (but in User_Role, since the roles are "permanent" and can be attached and detached freely.

Why select works correctly, but not update. please? If anymore info is needed - just ask - I'll try to answer all the secondary questions.

Update: the Role mapping:

  <class name="Role" lazy="false" table="Roles">
    <id name="Id" type="int">
      <generator class="native"/>
    </id>

    <property name="Name" />
    <property name="Description" />
  </class>

Update N2: this is how the tables are defined:

Role table:

CREATE TABLE [Roles] (
[Id] INTEGER NOT NULL PRIMARY KEY,
[Name] text  NOT NULL,
[LastChanged] INT NOT NULL DEFAULT(0)
);

CREATE UNIQUE INDEX uidxUserName ON Roles (Name COLLATE NOCASE);

User table:

CREATE TABLE [Users] (
[Id] INTEGER NOT NULL PRIMARY KEY,
[Name] text NOT NULL,
[LastChanged] INT NOT NULL DEFAULT(0)
);

CREATE UNIQUE INDEX uidxRoleName ON Users (Name COLLATE NOCASE);

User_Role relatioin table (foreign keys):

CREATE TABLE [User_Role] (
[UserId] INTEGER NOT NULL,
[RoleId] INTEGER NOT NULL,
[LastChanged] INT NOT NULL DEFAULT(0),
PRIMARY KEY (UserId, RoleId),
FOREIGN KEY (UserId) REFERENCES Users(Id),
FOREIGN KEY (RoleId) REFERENCES Roles(Id)
);

回答1:

I've ran into a similar problem myself.

Try to remove the inverse="true" on both the User collection and the Role collection and see if there's any difference. That worked for me.

There seems some unexpected behavior with many-to-many relationships and the inverse attribute. Perhaps someone else can explain why that occurs better than me. :)

Update: If I'm not mistaken here, you'll need to map a many-to-many bag under the Role mapping. Try to keep both inverse="false" or without the inverse attribute at all.
Are you certain about the foreign-key value used there?

Also, I think when mapping the class attribute, you need to provide the fully qualified name, i.e: Namespace.Class, Assembly.

Besides that, it looks mostly like my own mapping files.



回答2:

<bag name="RoleList" table="User_Role" cascade="save-update">
  <key column="UserId"/>
  <many-to-many class="Role" column="RoleId"/>
</bag>

Also: lazy="false" is almost always a bad idea.