RecentComments

Comment RSS

NHibernate inverse="true" and cascade="save-update" demo

by Ioannis 8. June 2009 12:58

 

We will work with the following database schema:

The corresponding domain model is as follows:

Entity.cs

public class Entity
{
 private long _iD;
 public virtual long ID
 {
     get { return _iD; }
     set { _iD = value;}
 }
 
 private string _description;
 public virtual string Description
 {
     get { return _description; }
     set { _description = value;}
 }
 
 private IList<Detail> _details;
 public virtual IList<Detail> Details
 {
     get { return _details; }
     set { _details = value; }
 }
(...)
Detail.cs
public class Detail:INotifyPropertyChanged,IEditableObject
{
    private long _iD;
    public virtual long ID
    {
        get { return _iD; }
        set { _iD = value; }
    }
 
    private string _line1;
    public virtual string Line1
    {
        get { return _line1; }
        set { _line1 = value; }
    }
 
    private string _line2;
    public virtual string Line2
    {
        get { return _line2; }
        set { _line2 = value; }
    }
 
    private Entity _relatedEntity;
    public virtual Entity RelatedEntity
    {
        get { return _relatedEntity; }
        set { _relatedEntity = value; }
    }
(...)

The first mapping file to be tested defines the association from both sides as follows:

Entity.hbm.xml
<bag name="Details" table="Details" cascade="save-update">
       <key column="EntityID"/>
       <one-to-many class="NHibernateTests.Detail,NHibernateTests"/>
</bag>
Detail.hbm.xml
<many-to-one name="RelatedEntity" column="EntityID" access="field.camelcase-underscore" cascade="save-update"/>

We instantiate a new Entity. We add two new Detail domain objects in the Details list and leave their “RelatedEntity” property to null. When we save the Entity domain object the following SQL is generated by NHibernate:

INSERT INTO Entities (Description) VALUES (@p0); select SCOPE_IDENTITY(); @p0 = 'Dokimi'
INSERT INTO Details (Line1, Line2, EntityID) VALUES (@p0, @p1, @p2); select SCOPE_IDENTITY(); @p0 = 'Test1', @p1 = 'Test1', @p2 = ''
INSERT INTO Details (Line1, Line2, EntityID) VALUES (@p0, @p1, @p2); select SCOPE_IDENTITY(); @p0 = 'Test2', @p1 = 'Test2', @p2 = ''
UPDATE Details SET EntityID = @p0 WHERE ID = @p1; @p0 = '16', @p1 = '33'
UPDATE Details SET EntityID = @p0 WHERE ID = @p1; @p0 = '16', @p1 = '34'
 
That is, NHibernate inserted the Detail domain objects and updated their EntityID column (the update was due to their inclusion in the Details list in the Entity Domain model since their RelatedEntity property was not set).
Now we also set the “RelatedEntity” for the Detail Domain Objects. When we save the Entity the following SQL is generated by NHibernate:
INSERT INTO Entities (Description) VALUES (@p0); select SCOPE_IDENTITY(); @p0 = 'Dokimi'
INSERT INTO Details (Line1, Line2, EntityID) VALUES (@p0, @p1, @p2); select SCOPE_IDENTITY(); @p0 = 'Test1', @p1 = 'Test1', @p2 = '17'
INSERT INTO Details (Line1, Line2, EntityID) VALUES (@p0, @p1, @p2); select SCOPE_IDENTITY(); @p0 = 'Test2', @p1 = 'Test2', @p2 = '17'
UPDATE Details SET EntityID = @p0 WHERE ID = @p1; @p0 = '17', @p1 = '35'
UPDATE Details SET EntityID = @p0 WHERE ID = @p1; @p0 = '17', @p1 = '36'
 
Note that now, the UPDATE SQL is not needed since the information about the relation (EntityID column) has already been set in the INSERT statements (due to the fact that the RelatedEntity property was set). In order to omit this we can set inverse=”true” as follows:
Entity.hbm.xml
<bagname="Details"table="Details"cascade="save-update" inverse="true">
       <keycolumn="EntityID"/>
       <one-to-manyclass="NHibernateTests.Detail,NHibernateTests"/>
</bag>
We run the same example as before and now:
INSERT INTO Entities (Description) VALUES (@p0); select SCOPE_IDENTITY(); @p0 = 'Dokimi'
INSERT INTO Details (Line1, Line2, EntityID) VALUES (@p0, @p1, @p2); select SCOPE_IDENTITY(); @p0 = 'Test1', @p1 = 'Test1', @p2 = '17'
INSERT INTO Details (Line1, Line2, EntityID) VALUES (@p0, @p1, @p2); select SCOPE_IDENTITY(); @p0 = 'Test2', @p1 = 'Test2', @p2 = '17'
That is, inverse=”true” has caused the UPDATE SQL statements to be omitted (although the cascade has added the appropriate detail records).

 

kick it on DotNetKicks.com

Shout it

Tags:

Comments

6/8/2009 11:29:01 AM #

trackback

Trackback from DotNetKicks.com

NHibernate inverse=

DotNetKicks.com

6/8/2009 11:32:38 AM #

trackback

Trackback from DotNetShoutout

C# and .NET Tips and Tricks | NHibernate inverse="true" and cascade="save-update" demo

DotNetShoutout

7/14/2009 2:50:41 AM #

pingback

Pingback from answerspluto.com

list of urls - 5 « Answers Pluto

answerspluto.com

7/22/2010 10:21:16 AM #

mynkow

Hi, Great article. However I am not able to reproduce it in my code. Please take a look here: stackoverflow.com/.../unnecessary-updates-with-bidirectional-mapping

What I am doing wrong?

Best Regards

mynkow Bulgaria

Add comment


(Will show your Gravatar icon)

Enter the word
CAPTCHA word
Add 1 to the number above


  Country flag

biuquote
  • Comment
  • Preview
Loading



Powered by BlogEngine.NET 1.5.0.7

Programming Blogs - BlogCatalog Blog Directory Add to Technorati Favorites

MVP Award

Ioannis Panagopoulos





This blog is using BlogEngine.Net and is hosted in the hoster below. I have not experienced any problems installing BlogEngine.Net in the host and I am satisfied with the host's response times. Therefore I recommend it.


DiscountASP Add