2

Hi I have Request class which contains Document one-to-many mapping.

Request class

public class Request
{
virtual public int Id
    {
        get;
        set;
    }
...
virtual public Iesi.Collections.Generic.ISet<Document> Documents
  {
       get;
       set;
  }
}

Document class

public class Document
{
public virtual int Id
{
    get;
    set;
}

public virtual int ParentEntityId
{
    get;
    set;
}
}

XML Mapping looks like this: REQUEST

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
    assembly="xxxx"
    namespace="xxxx.Domain">
<class name="Request" table="tbl_Req">
    <id name="Id" column="req_id">
    <generator class="native"></generator>
        </id>
    <set name="Documents" cascade="all-delete-orphan"  inverse="false">
        <key column="doc_parent_ent_id" not-null="true"/>
            <one-to-many class="xxxx.Domain.Document"/>
    </set>
</class>  
</hibernate-mapping>

DOCUMENT looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
    assembly="xxxx"
    namespace="xxxx.Domain">
<class name="Document"  table="tbl_doc">
<id name="Id" column="doc_id">
    <generator class="native"></generator>
</id>
</class>
</hibernate-mapping>

Now at this configuration when I save document NHibernate creates

INSERT INTO tbl_doc (doc_digimage_code, doc_lnk_filename, doc_lnk_filepath, doc_timestamp, doc_author, doc_parent_ent_id) VALUES (@p0, @p1, @p2, @p3, @p4, @p5); select SCOPE_IDENTITY()',N'@p0 nvarchar(4000),@p1 nvarchar(4000),@p2 nvarchar(4000),@p3 datetime,@p4 int,@p5 int',@p0=N'1',@p1=NULL,@p2=NULL,@p3='2013-02-28 18:05:45',@p4=7353,@p5=174

and

UPDATE tbl_doc SET doc_parent_ent_id = @p0 WHERE doc_id = @p1',N'@p0 int,@p1 int',@p0=174,@p1=32

I dont unerstand why NHibernate generates INSERT and UPDATE when its updating field which already has correct value.

I also found this post NHibernate insert generates updates for collection items which is suggesting using inverse, but when I add it to mapping then ParentEntityId is filled with 0.

Thanks

Community
  • 1
  • 1
MightyPolo
  • 103
  • 9

1 Answers1

2

Change your Document class to refer Request class instead of ParentEntityId.

public class Document
{
  public virtual int Id
  {
    get;
    set;
  }

  public virtual Request ParentEntity
  {
    get;
    set;
  }
}

Set inverse = true on Documents which will not issue additional update statements when you try to insert new Requests.

    <set name="Documents" cascade="all-delete-orphan"  **inverse="true"**>
        <key column="doc_parent_ent_id" not-null="true"/>
            <one-to-many class="xxxx.Domain.Document"/>
    </set>

But specifying inverse = true means that Document object should take care of the relationship by itself i.e., whenever a new document is added to the Request documents list be sure to set ParentEntity property.

Request objRequest = new Request();    
objRequest.Documents = new Iesi.Collections.Generic.ISet<Document>() 
                            { 
                                 new Document() { Id = 1, ParentEntity = objRequest }  
                            };

By having inverse=false, which is by default, it is not required to set ParentEntity property, NHibernate will automatically detect the relationship. But it comes with additional update statement which we are trying to avoid here.

Finally, include many-to-one relationship in Document mapping.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
    assembly="xxxx"
    namespace="xxxx.Domain">
<class name="Document"  table="tbl_doc">
<id name="Id" column="doc_id">
    <generator class="native"></generator>
</id>

**<many-to-one cascade="none" class="xxx.Request" name="ParentEntity">
  <column name="doc_parent_ent_id" not-null="true" />
</many-to-one>**

</class>
</hibernate-mapping>
Sunny
  • 4,765
  • 5
  • 37
  • 72