开发者

To cascade or not to cascade? ("object references an unsaved transient instance" error)

First, I've tried to ask the similar question yesterday (NHibernate many-to-many relationship question: can select, can't update), but after a debugging night hopefully I can rephrase a question the better (right?) way. If I am doing something wrong by that - please tell - I'll erase the post.

Here comes the description followed by a real question:

Given USER, ROLE and USER_ROLE tables which keep Users, Roles and the many-to-many unidirectional relation respectively. Currently, User has a bag of Roles and that's it:

USER:

  <class name="User" lazy="false" table="Users">
    <id name="Id" type="int">
      <generator class="native"/>
    </id>
    <version name="m_lastChanged" ac开发者_运维技巧cess="field" column="LastChanged" generated="never" type="int"/>

    <property name="Name" />

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

  </class>

ROLE (there are currently very very few of them):

  <class name="Role" lazy="false" table="Roles">
    <id name="Id" type="int">
      <generator class="native"/>
    </id>
    <version name="m_lastChanged" access="field" column="LastChanged" generated="never" type="int"/>

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

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

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

When User is fetched (I am tracking the SQL queries) – its relations AND roles are fetched as well:

SELECT
    rolelist0_.UserId as UserId1_,
    rolelist0_.RoleId as RoleId1_,
    role1_.Id as Id2_0_,
    role1_.LastChanged as LastChan2_2_0_,
    role1_.Name as Name2_0_,
    role1_.Description as Descript4_2_0_
FROM
    User_Role rolelist0_
left outer join
    Roles role1_
        on rolelist0_.RoleId=role1_.Id
WHERE
    rolelist0_.UserId=@p0;
@p0 = 2

SELECT
    user0_.Id as Id3_0_,
    user0_.LastChanged as LastChan2_3_0_,
    user0_.Name as Name3_0_,
    user0_.Password as Password3_0_,
    user0_.FullName as FullName3_0_,
    user0_.EMail as EMail3_0_,
    user0_.PhoneNumber as PhoneNum7_3_0_,
    user0_.Description as Descript8_3_0_
FROM
    Users user0_
WHERE
    user0_.Id=@p0;
@p0 = 2

And here comes the problem: when I am trying to save User then deep in the debugger the NHibernate checks the LastUpdated value of Role object and throws NHibernate.TransientObjectException (object references an unsaved transient instance - save the transient instance before flushing), telling that I need to save Role first. While that the role is still unmodified.

I've tried to apply the "save-update" and "all" and other types of cascaded on User (no changes while fetching) but then when saving User it tries to save Role first and I am getting an exception that the role uniqueness constraint is violated.

So, if appropriate, can you point what am I missing here, please?

Update: By accident modified the Role mapping in the following way (added unsaved-value="undefined"):

<version name="m_lastChanged" access="field" column="LastChanged" unsaved-value="undefined" generated="never" type="int"/>

The queries seem to be alright. Is it the correct/best solution, please?


So, to make the long story short (and thanks to Ayende) the version field LastUpdated should be initialized to 1, not to 0. Then it all orchestrates in a lovely symphony.

So incredible how much difference can be carried in a single bit :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜