-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 
Author Message
 Post subject: Problem with one to many mapping
PostPosted: Wed Aug 08, 2007 6:18 am 
Newbie

Joined: Mon Aug 06, 2007 9:42 am
Posts: 9
Hello, I'm new at NHibernate.
I'm using a Firebird database.

I created a very simple "table per hierarchy" system (base class A and derived class C which are associated to a database table TA), which is working (adding, selecting ok).

Now, in my base class A, I add a "one to many set", to another class B associated to a table TB.
Everything is ok until a add data :

I create an instance C_inst of a class C derived from A.
I fill it with data, including a set of B instances.

If I watch my C instance, evething looks fine. I can see data in it, as well as my set which is full of B instances.

But when I commit, nothing is created in table TB !
By the way, data was added to table TA...
How is that possible ?
I get no exception and no log4net error


m_Session.Save(C_inst);
tx.Commit();
m_Session.Flush();
---> here C_inst is OK, as count of C_inst.my_set_of_B is > 0
m_Session.Refresh(C_inst);
---> here C_inst has an empty C_inst.my_set_of_B


Thanks a lot !


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 08, 2007 7:24 am 
Regular
Regular

Joined: Thu Nov 23, 2006 10:29 am
Posts: 106
Location: Belgium
Hi,

Could you eventually post the mappings of your A,B and C classes and some code ?

_________________
Please rate this post if it helped.

X.


Top
 Profile  
 
 Post subject: Code
PostPosted: Wed Aug 08, 2007 7:53 am 
Newbie

Joined: Mon Aug 06, 2007 9:42 am
Posts: 9
Ok, sorry for long code but I prefer posting the real code.

Class A:

Code:
namespace SocomecDBBenchMark.NHibernateDatabaseStructure
{
    /// <summary>
    /// Summary description for CDevice
    /// </summary>
    public class CDevice
    {
        private string m_sID;
        private string m_sType;
        private string m_sName;
        private ISet m_lMeasures;

        public CDevice()
        {
            Name = "Unknown Device";
            Type = "CDevice";
        }

        protected CDevice(string s_name)
        {
            Name = s_name;
        }
       
        public virtual ISet Measures
        {
            get
            {
                return m_lMeasures;
            }
            set
            {
                m_lMeasures = value;
            }
        }
       
        public virtual string Id
        {
            get
            {   
                return m_sID;     
            }
            set
            {
                m_sID = value;
            }
        }

        public virtual string Type
        {
            get
            {
                return m_sType;
            }
            set
            {
                m_sType = value;
            }
        }

        public virtual string Name
        {
            get
            {
                return m_sName;
            }
            set
            {
                m_sName = value;
            }
        }
    }
}


Class C : (I don't post the code for all inheritance graph : ExtendedDevice and CountisDevice and DirisDevice)

Code:

namespace SocomecDBBenchMark.NHibernateDatabaseStructure
{
    /// <summary>
    /// Summary description for CD18Device
    /// </summary>
    public class D18Device : DirisDevice // which inherits from ExtendedDevice which itself inherits from Device
    {
        private int IPPort;               // not stored in db yet
        private string IPAddress;  // not stored in db yet

        public D18Device()
        {
        }

        public D18Device(string s_name)
            : base(s_name, 1035)
        {
        }

        public override string ToString()
        {
            return String.Format("{0} IPAddress={1}", base.ToString(), IPAddress);
        }
    }
}



Mapping for A (Device) and C (D18):

Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">


<!-- ********************************************************************** -->
<!--                      Device                                            --> 
<!--                         -> ExtendedDevice                              -->   
<!--                                -> Diris                                -->   
<!--                                    -> D18                              -->   
<!-- ********************************************************************** -->

<class name="SocomecDBBenchMark.NHibernateDatabaseStructure.CDevice" table="Device">
<!-- A 32 hex character is our surrogate key. It's automatically
generated by NHibernate with the UUID pattern. -->
<id name="Id">
<column name="ID" sql-type="char(32)" not-null="true"/>
<generator class="uuid.hex" />
</id> 
<discriminator column="SUBCLASS" length="30"/>
<property name="Name">
<column name="Name" length="40" />
</property>
<property name="Type">
<column name="Type" length="50" />
</property>

  <!-- Measures -->
  <set name="Measures" inverse="true">
  <key column="DEVICE_ID"/>
  <one-to-many class="SocomecDBBenchMark.NHibernateDatabaseStructure.CMeasure"/>
  </set> 
 
  <!-- Extended Device -> Device --> 
  <subclass name="SocomecDBBenchMark.NHibernateDatabaseStructure.ExtendedDevice" discriminator-value="Extended">
  <property name="Weight" column="WEIGHT" />

  <!-- DirisDevice -> Extended Device --> 
   
  <subclass name="SocomecDBBenchMark.NHibernateDatabaseStructure.DirisDevice" discriminator-value="Diris">

  <!-- D18 -> DirisDevice --> 

    <subclass name="SocomecDBBenchMark.NHibernateDatabaseStructure.D18Device" discriminator-value="D18">
    </subclass>
<!--   
  <property name="Inputs" column="INPUTS" />
  -->
  </subclass>
</subclass>   
</class> 

</hibernate-mapping>


Class B (Measures)

Code:
/// <summary>
/// Summary description for CMeasure
/// </summary>
namespace SocomecDBBenchMark.NHibernateDatabaseStructure
{
    /// <summary>
    /// Summary description for CMeasure
    /// </summary>
    public class CMeasure
    {
        private string m_sID;
        private int m_iAvgEnergy;
        private int m_iPhase1;
        private int m_iPhase2;
        private int m_iPhase3;
        private int m_iVal1;
        private int m_iVal2;
        private int m_iVal3;

        public virtual string Id
        {
            get
            {
                return m_sID;
            }
            set
            {
                m_sID = value;
            }
        }

        public virtual int AvgEnergy
        {
            get
            {
                return m_iAvgEnergy;
            }
            set
            {
                m_iAvgEnergy = value;
            }
        }

        public virtual int Phase1
        {
            get
            {
                return m_iPhase1;
            }
            set
            {
                m_iPhase1 = value;
            }
        }

        public virtual int Phase2
        {
            get
            {
                return m_iPhase2;
            }
            set
            {
                m_iPhase2 = value;
            }
        }

        public virtual int Phase3
        {
            get
            {
                return m_iPhase3;
            }
            set
            {
                m_iPhase3 = value;
            }
        }

        public virtual int Val1
        {
            get
            {
                return m_iVal1;
            }
            set
            {
                m_iVal1 = value;
            }
        }

        public virtual int Val2
        {
            get
            {
                return m_iVal2;
            }
            set
            {
                m_iVal2 = value;
            }
        }

        public virtual int Val3
        {
            get
            {
                return m_iVal3;
            }
            set
            {
                m_iVal3 = value;
            }
        }

        /// <summary>
        /// Default ctor with default init values
        /// </summary>
        public CMeasure()
        {
            AvgEnergy = 10;
            Phase1 = 20;
            Phase2 = 30;
            Phase3 = 40;
            Val1 = 1;
            Val2 = 2;
            Val3 = 3;
        }
    }
}


Mapping for B (Measures)

Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">

<!-- ********************************************************************** -->
<!--                      Measures                                          --> 
<!-- ********************************************************************** -->
<class name="SocomecDBBenchMark.NHibernateDatabaseStructure.CMeasure" table="MEASURE">
<!-- A 32 hex character is our surrogate key. It's automatically
generated by NHibernate with the UUID pattern. -->
<id name="Id">
<column name="ID" sql-type="char(32)" not-null="true"/>
<generator class="uuid.hex" />
</id> 
  <property name="AvgEnergy" column="AVGENERGY" />
  <property name="Phase1" column="PHASE1" />
  <property name="Phase2" column="PHASE2" />
  <property name="Phase3" column="PHASE3" />
  <property name="Val1" column="VAL1" />
  <property name="Val2" column="VAL2" />
  <property name="Val3" column="VAL3" /> 
</class>         
</hibernate-mapping>


Main code for adding device and measures:

Code:
        public override void CreateManyLinesWithMeasuresCore()
        {
            if (m_Session != null)
            {
                ITransaction tx = m_Session.BeginTransaction();

                for (int i = 0; i < 10; i++)
                {
                    D18Device o_d18 = new D18Device(String.Format("D18 no {0}", i + 1));
                    ISet my_measures = new HashedSet();
                   
                    for (int j = 0; j < CBaseBench.m_iMAX_MEASURES; j++)
                    {
                        CMeasure my_mesure = new CMeasure();
                        my_mesure.AvgEnergy = 12;
                        my_measures.Add(my_mesure);
                    }
                                         
                    o_d18.Measures = my_measures;

                    m_Session.Save(o_d18);
                    tx.Commit();
                    m_Session.Flush();
                    m_Session.Refresh(o_d18);
                }
     }
}
[/code]


Top
 Profile  
 
 Post subject: And DDL for Firebird
PostPosted: Wed Aug 08, 2007 7:58 am 
Newbie

Joined: Mon Aug 06, 2007 9:42 am
Posts: 9
Device table :
Code:
CREATE TABLE DEVICE (
  ID CHAR(32) CHARACTER SET WIN1252 NOT NULL COLLATE WIN1252,
  "TYPE" VARCHAR(50) CHARACTER SET WIN1252 COLLATE WIN1252,
  NAME CHAR(40) CHARACTER SET WIN1252 COLLATE WIN1252,
  WEIGHT INTEGER,
  SUBCLASS VARCHAR(30) CHARACTER SET WIN1252 NOT NULL COLLATE WIN1252);



Measure table:
Code:
CREATE TABLE MEASURE (
  AVGENERGY INTEGER,
  PHASE1 INTEGER,
  PHASE2 INTEGER,
  PHASE3 INTEGER,
  VAL1 INTEGER,
  VAL2 INTEGER,
  VAL3 INTEGER,
  ID CHAR(32) CHARACTER SET WIN1252 NOT NULL COLLATE WIN1252,
  DEVICE_ID CHAR(32) CHARACTER SET WIN1252 DEFAULT 0 NOT NULL COLLATE WIN1252);



As I said before, inserting a device works but nothing is stored in table 'measure'.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 08, 2007 8:10 am 
Regular
Regular

Joined: Thu Nov 23, 2006 10:29 am
Posts: 106
Location: Belgium
Hello,

You mapped your set as "inverse" which means NHibernate will not fill in the DeviceID column in the measure table for you. Also, you might consider setting a cascade tag.

Removing the inverse clause should solve it.
Or: create a bidirectional association in CMeasure pointing to Device, and fill it in.

Could you try that and let me know if it helps ?

_________________
Please rate this post if it helped.

X.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 08, 2007 8:22 am 
Newbie

Joined: Mon Aug 06, 2007 9:42 am
Posts: 9
Yes I already tried this but I get the following error on the commit statement :
"object references an unsaved transient instance - save the transient instance before flushing: SocomecDBBenchMark.NHibernateDatabaseStructure.CMeasure"


I didn't add any bidirectional association yet (didn't want to add an mighty bug with this).
Maybe I should do that ?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 08, 2007 8:30 am 
Regular
Regular

Joined: Thu Nov 23, 2006 10:29 am
Posts: 106
Location: Belgium
Hello,

I think removing the inverse-tag, and adding a cascade-tag (f.e. "all-delete-orphan") should be enough.

_________________
Please rate this post if it helped.

X.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 08, 2007 9:21 am 
Newbie

Joined: Mon Aug 06, 2007 9:42 am
Posts: 9
Ok now this works !

First I tried an bidirectional association. But it didn't work.
Then I delete the inverse and the bidirectional association, and added the cascase.
Then it was OK. Thanks a lot !!!!

I must say that I have MANY difficult with Nhybernate.

I'm trying to make a benchmak between DLINQ, LINQ to Entity, Db4o and NHibernate.
NHibernate is the last one that I test, and I spent a lot of time compared to the others.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 08, 2007 9:36 am 
Regular
Regular

Joined: Thu Nov 23, 2006 10:29 am
Posts: 106
Location: Belgium
Yeah, but it's fun, isn't it ? ;-)

I agree that NHibernate has a very steep learning curve, but that's a logical consequence of the fact that (N)Hibernate is just so incredibly powerful.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.