Why is NHibernate doing an UPDATE rather than an INSERT?
Continuing my explorations in NHibernate with my podcast application, I've come across something odd开发者_开发技巧: NHibernate is UPDATEing when I would expect an INSERT. The situation is a simple one-to-many relationship between a podcast and its items. Here's my NHibernate mapping:
<hibernate-mapping assembly="App.DataModel">
<class name="Feed" table="Feeds">
<!-- snip -->
<bag name="FeedItems" table="FeedItems" cascade="all">
<key column="FeedId" />
<one-to-many class="FeedItem" />
</bag>
</class>
</hibernate-mapping>
The situation is: I've created a new Podcast
object, updated it from the feed (so the Podcast.FeedItems
collection property contains a number of FeedItem
s) and am now saving it to the database via ISession.Save()
. Judging by the NHibernate log file, the Podcast
object is correctly inserted into the database, but the FeedItems
collection is being UPDATEd instead. Here's the SQL generated for the Podcast
:
INSERT INTO Feeds (
Uri, IsPublic, Title, Description, Link, Language, Copyright,
LastBuildDate, PublishDate, Docs, Webmaster, Author, Subtitle,
Summary, OwnerName, OwnerEmail, IsExplicit, ImageUri, Id
) VALUES (
@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11,
@p12, @p13, @p14, @p15, @p16, @p17, @p18
);
And here's the SQL generated for the FeedItem
s:
UPDATE FeedItems SET PublishDate = @p0, Author = @p1,
IsExplicit = @p2, Subtitle = @p3, Summary = @p4,
Duration = @p5 WHERE Id = @p6;
I don't get why an UPDATE is happening when the FeedItem
s don't necessarily even exist yet. I'm chasing this down, because the test that exercises this code is failing with the exception
NHibernate.StaleStateException: Unexpected row count: 0; expected: 1
Update with more logging: Following some more tweaks, I spotted the following line in the NHibernate log:
Collection found: [Podcast.FeedItems#GUID], was: [<unreferenced>] (initialized)
The key to this issue was the exception message
NHibernate.StaleStateException: Unexpected row count: 0; expected: 1
Thanks to this question I realised that my IDs were being assigned by my own code and not by NHibernate, which caused NHibernate to think that the entities had already been saved. Once I removed the code auto-generating new IDs, the problem went away.
I've seen this happen when the unsaved-value
attribute on my element didn't match up against the corresponding property value for a new entity. Here's an example:
<class name="Foo">
<id name="ID" unsaved-value="-1" type="Int32">
<generator class="native"/>
</id>
</class>
and
public class Foo
{
private int _id = 0;
public int ID {
get { return _id; }
set { _id = value; }
}
}
In this case, saving a new Foo will result in NHib generating an UPDATE since it thinks that the object already has an identity.
精彩评论