Sergey,
Thanks for the reply. The more I look at this, the more that I am sure it is a bug. Let me know if you agree and I need to file it somewhere.
I was wrong about it being related to transient objects. The extra UPDATE statement happens when :
- The object to be deleted has a bag of children objects, AND
- The object to be deleted has a timestamp/version column
To reproduce I created a small example, a 'Student' class with child 'Book' objects. Here is the code that I execute:
Code:
ISessionFactory factory = cfg.BuildSessionFactory();
Student s = new Student("Fred", "fred@test.com");
Book b = new Book("Math 101", s);
s.Books.Add(b);
using (ISession session = factory.OpenSession())
{
// Create
session.Save(s);
session.Flush();
// Unexpected UPDATE statement happens on this call before the delete statement
session.Delete(s);
session.Flush();
}
Here are the table definitions:
Code:
CREATE TABLE Student(
[id] [int] IDENTITY(1,1) NOT NULL,
[name] [varchar](50) NOT NULL,
[email] [varchar](50) NOT NULL,
[lastupdate] [datetime] NOT NULL)
CREATE TABLE Book(
[id] [int] IDENTITY(1,1) NOT NULL,
[studentid] [int] NOT NULL,
[name] [varchar](50))
Here are the mapping files:
Code:
<class name="Student" table="Student" lazy="false">
<id name="Id" column="id" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<version type="timestamp" name="LastUpdate" column="lastupdate" />
<bag name="Books" lazy="false" inverse="true" cascade="all-delete-orphan">
<key column="studentid" />
<one-to-many class="Book"/>
</bag>
<property column="name" type="String" name="Name" not-null="true" />
<property column="email" type="String" name="Email" not-null="true" />
</class>
<class name="Book" table="Book" lazy="false">
<id name="Id" column="id" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<many-to-one name="Student" class="Student" column="studentid" />
<property column="name" type="String" name="Name" not-null="true" />
</class>
And finally, here is the SQL (note the unexpected UPDATE statement):
Code:
NHibernate: INSERT INTO Student (lastupdate, name, email) VALUES (@p0, @p1, @p2); select SCOPE_IDENTITY(); @p0 = '10/26/2006 9:07:06 AM', @p1 = 'Fred', @p2 = 'fred@test.com'
NHibernate: INSERT INTO Book (studentid, name) VALUES (@p0, @p1); select SCOPE_IDENTITY(); @p0 = '8', @p1 = 'Math 101'
NHibernate: UPDATE Student SET lastupdate = @p0, name = @p1, email = @p2 WHERE id = @p3 AND lastupdate = @p4; @p0 = '10/26/2006 9:07:06 AM', @p1 = 'Fred', @p2 = 'fred@test.com', @p3 = '8', @p4 = '10/26/2006 9:07:06 AM'
NHibernate: DELETE FROM Book WHERE id = @p0; @p0 = '3'
NHibernate: DELETE FROM Student WHERE id = @p0 AND lastupdate = @p1; @p0 = '8', @p1 = '10/26/2006 9:07:06 AM'