-->
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 when saving objects
PostPosted: Sat Jul 09, 2005 4:18 am 
Beginner
Beginner

Joined: Fri May 20, 2005 5:06 am
Posts: 28
1.) The problem

step A) I make a new object in my App, call session.Save() and session.Flush(). Everything works fine.

step B) Then I do the same stuff again => exception. Funny thing: the object is saved in the DB corretly.

2.) Debugging through NHibernate (all in class SessionImpl)

I found out that the IdentityMap entityEntries is after step A (see above) ok: last entry is my object i want to save. After step B the last object is also ok (the new one i want to save), but the one before (the one I already saved in step A) forgott all its references.

After further investigation I found in line 986 the following:

Code:
// Put a placeholder in entries, so we don't recurse back to try and Save() the same object again.
// QUESTION: Should this be done before OnSave()/OnUpdate() is called?
AddEntry( obj, Status.Saving, null, id, null, LockMode.Write, useIdentityColumn, persister, false );


I'm not sure if this is was causes my troubles, but I appreaciate any help you can give me.

Thanks, Rainer.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 10, 2005 10:12 am 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
Can you give us the code you are executing and the content of your log.txt file? (the exception can give useful information)

_________________
Pierre Henri Kuaté.
Get NHibernate in Action Now!


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 10, 2005 1:09 pm 
Beginner
Beginner

Joined: Fri May 20, 2005 5:06 am
Posts: 28
Everything I wrote in my first post is still valid. Here are some explanations:

The object I'm trying to save is called Physical and the Employee is a field in it.

First the exception + stack trace:

Code:
not-null property references a null or transient value: Physical, Employee

Stack Trace:
   at NHibernate.Impl.SessionImpl.CheckNullability(Object[] values, IClassPersister persister, Boolean isUpdate)
   at NHibernate.Impl.SessionImpl.FlushEntity(Object obj, EntityEntry entry)
   at NHibernate.Impl.SessionImpl.FlushEntities()
   at NHibernate.Impl.SessionImpl.FlushEverything()
   at NHibernate.Impl.SessionImpl.Flush()
   at BitConstruct.PatientManager.Model.Services.EntityService.Save(BaseEntity entityObject) in C:\Dokumente und Einstellungen\Rainer\Eigene Dateien\Visual Studio Projects\PatientManager\Model\Services\EntityService.cs:line 219
   at BitConstruct.PatientManager.Client.Forms.Templates.ModifyForm.btnOK_Click(Object sender, EventArgs e) in C:\Dokumente und Einstellungen\Rainer\Eigene Dateien\Visual Studio Projects\PatientManager\Client\Forms\Templates\ModifyForm.cs:line 199
   at BitConstruct.PatientManager.Client.Forms.Modify.Physical.btnOK_Click(Object sender, EventArgs e) in c:\dokumente und einstellungen\rainer\eigene dateien\visual studio projects\patientmanager\client\forms\modify\physical.cs:line 584
   at System.Windows.Forms.Control.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ButtonBase.WndProc(Message& m)
   at System.Windows.Forms.Button.WndProc(Message& m)
   at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


My saving code is the following (entityObject is my new physical):

Code:
session.SaveOrUpdate(entityObject);
session.Flush();


The exception is thrown in teh flush line. The funny thing is, the object is saved in the DB.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 10, 2005 4:57 pm 
Expert
Expert

Joined: Fri May 13, 2005 5:56 pm
Posts: 308
Location: Santa Barbara, California, USA
show mapping file for Physical and Employee objects, please. Also, please show the code you are using to instantiate Physical object. I am guessing you have Employee property of Phisicaly mapped as a many-to-one back to Employee with the not-null="true" value. However, your data model may not be requiring an EmployeeID in the Physical table. You may also be creating a Physical without setting the Employee property. This is just a guess, however. As I mentioned, Please post more info.

-devon


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 11, 2005 3:30 am 
Beginner
Beginner

Joined: Fri May 20, 2005 5:06 am
Posts: 28
Mapping file for Employee:

Code:
<class name="BitConstruct.PatientManager.Model.Entities.Employee, BitConstruct.PatientManager.Model"
      table="Employees">
      <id name="Id" unsaved-value="0" access="nosetter.pascalcase-m-underscore" type="Int32"
         column="EmployeeId">
         <generator class="identity" />
      </id>
      <property name="Country" column="Country" />
      <many-to-one name="Firm" column="Firm_FirmId" class="BitConstruct.PatientManager.Model.Entities.Firm, BitConstruct.PatientManager.Model"
         not-null="true" outer-join="false" />
      <many-to-one name="InsuranceCompany" column="InsuranceCompany_InsuranceCompanyId" class="BitConstruct.PatientManager.Model.Entities.InsuranceCompany, BitConstruct.PatientManager.Model"
         not-null="true" outer-join="false" />
      <many-to-one name="Job" column="Job_JobId" class="BitConstruct.PatientManager.Model.Entities.Job, BitConstruct.PatientManager.Model"
         outer-join="false" />
      <property name="Active" column="Active" type="Boolean" />
      <property name="Title" column="Title" type="String" />
      <property name="FirstName" column="FirstName" type="String" />
      <property name="LastName" column="LastName" type="String" not-null="true" />
      <property name="Birthday" column="Birthday" type="Nullables.NHibernate.NullableDateTimeType, Nullables.NHibernate" />
      <property name="Sex" column="Sex" />
      <property name="InsuranceNumber" column="InsuranceNumber" type="String" />
      <property name="Street" column="Street" type="String" />
      <property name="ZipCode" column="ZipCode" type="Int32" />
      <property name="City" column="City" type="String" />
      <property name="Telephone" column="Telephone" type="String" />
      <property name="Fax" column="Fax" type="String" />
      <property name="Mobile" column="Mobile" type="String" />
      <property name="Email" column="Email" type="String" />
      <bag name="Pollutions" table="Employees_Substances" lazy="true" access="nosetter.pascalcase-m-underscore">
         <key column="EmployeeId" />
         <many-to-many column="Pollutions_SubstanceId" class="BitConstruct.PatientManager.Model.Entities.Substance, BitConstruct.PatientManager.Model" />
      </bag>
      <bag name="Physicals" inverse="true" lazy="true" access="nosetter.pascalcase-m-underscore"
         cascade="all">
         <key column="Employee_EmployeeId" />
         <one-to-many class="BitConstruct.PatientManager.Model.Entities.Physical, BitConstruct.PatientManager.Model" />
      </bag>
      <bag name="VaccinationPlan" table="Employees_Vaccines" lazy="true" access="nosetter.pascalcase-m-underscore">
         <key column="EmployeeId" />
         <many-to-many column="VaccinationPlan_VaccineId" class="BitConstruct.PatientManager.Model.Entities.Vaccine, BitConstruct.PatientManager.Model" />
      </bag>
   </class>


Mapping file for Physical:

Code:
<class name="BitConstruct.PatientManager.Model.Entities.Physical, BitConstruct.PatientManager.Model"
      table="Physicals">
      <id name="Id" unsaved-value="0" access="nosetter.pascalcase-m-underscore" type="Int32"
         column="PhysicalId">
         <generator class="identity" />
      </id>
      <many-to-one name="Doctor" column="Doctor_DoctorId" class="BitConstruct.PatientManager.Model.Entities.Doctor, BitConstruct.PatientManager.Model"
         outer-join="false" />
      <many-to-one name="Employee" column="Employee_EmployeeId" class="BitConstruct.PatientManager.Model.Entities.Employee, BitConstruct.PatientManager.Model"
         not-null="true" outer-join="false" />
      <property name="PhysicalDate" column="PhysicalDate" type="DateTime"
         not-null="true" />
      <property name="PhysicalState" column="PhysicalState" not-null="true" />
      <many-to-one name="InformationHeader" column="InformationHeader_InformationHeaderId" class="BitConstruct.PatientManager.Model.Entities.InformationHeader, BitConstruct.PatientManager.Model"
         outer-join="false" />
      <many-to-one name="SalesHeader" column="SalesHeader_SalesHeaderId" class="BitConstruct.PatientManager.Model.Entities.SalesHeader, BitConstruct.PatientManager.Model"
         outer-join="false" />
      <property name="Comment" column="Comment" type="String" />
      <property name="FirmAttestation" column="FirmAttestation" type="String" />
      <property name="EmployeeAttestation" column="EmployeeAttestation" type="String" />
      <property name="PhysicalResult" column="PhysicalResult" />
      <property name="BodilyExamination" column="BodilyExamination" type="Boolean" />
      <property name="BodilyComplaint" column="BodilyComplaint" type="Boolean" />
      <bag name="PhysicalComments" table="Comments_Physicals" lazy="true" access="nosetter.pascalcase-m-underscore">
         <key column="PhysicalId" />
         <many-to-many column="PhysicalComments_CommentId" class="BitConstruct.PatientManager.Model.Entities.Comment, BitConstruct.PatientManager.Model" />
      </bag>
      <bag name="TestedParameters" inverse="true" lazy="true" access="nosetter.pascalcase-m-underscore"
         cascade="all-delete-orphan">
         <key column="Physical_PhysicalId" />
         <one-to-many class="BitConstruct.PatientManager.Model.Entities.TestedParameter, BitConstruct.PatientManager.Model" />
      </bag>
      <bag name="TestedSubstances" inverse="true" lazy="true" access="nosetter.pascalcase-m-underscore"
         cascade="all-delete-orphan">
         <key column="Physical_PhysicalId" />
         <one-to-many class="BitConstruct.PatientManager.Model.Entities.TestedSubstance, BitConstruct.PatientManager.Model" />
      </bag>
      <bag name="Vaccinations" inverse="true" lazy="true" access="nosetter.pascalcase-m-underscore"
         cascade="all-delete-orphan">
         <key column="Physical_PhysicalId" />
         <one-to-many class="BitConstruct.PatientManager.Model.Entities.Vaccination, BitConstruct.PatientManager.Model" />
      </bag>
   </class>


Instantiate Code:
Code:
Physical newPhysical = new Physical();


After that a window pops up, where the user must enter the some fields, one of them is the Employee field. If selected and ok is pressed, then the save code starts. Which, I have again to say, works the first time completly fine, and the second time is the exception, but it is also correctly saved to the DB (with the correct Employee reference). I still think the problem is, that the first object is somehow corrupted because it forgot its references in the IdentityMap entityEntries.

Hope that helps, and thanks for all of your help.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 11, 2005 8:36 am 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
What are you doing between
Code:
Physical newPhysical = new Physical();

and
Code:
session.SaveOrUpdate(newPhysical);
session.Flush();


As you set
Code:
<many-to-one name="Employee"  [...] not-null="true" [...] />


You must initialize newPhysical.Employee ! (it can not be null)

_________________
Pierre Henri Kuaté.
Get NHibernate in Action Now!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 11, 2005 2:27 pm 
Beginner
Beginner

Joined: Fri May 20, 2005 5:06 am
Posts: 28
As I wrote in my last email, a window pops up. It shows all fileds of the physical. There is also a combobox whixh is filled with all employees. The user must select one of them. Then he is allowed to press the save button. And that's where the save code is.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 12, 2005 12:17 am 
Expert
Expert

Joined: Fri May 13, 2005 5:56 pm
Posts: 308
Location: Santa Barbara, California, USA
Okay, post all of the code in the SaveButton_Click event handler then. We are trying to make sure that you are completing all of the steps before calling session.SaveOrUpdate().

You are saying your code looks like this:

Code:
private SaveButton_Click(object sender, eventargs e) {
  Physical newPhysical = new Physical();
  session.SaveOrUpdate(newPhysical);
  session.Flush();
}


We want to make sure you are at least doing:

Code:
private SaveButton_Click(object sender, eventargs e) {
  Physical newPhysical = new Physical();
  newPhysical.Employee = session.Load(typeof(Employee), Int32.Parse(this.EmployeeComboBox.SelectedValue));
  session.SaveOrUpdate(newPhysical);
  session.Flush();
}


Or at least something similar. The point is, you have to make sure you are setting the newPhysical.Employee property. As I mentioned, you have the property mapped as not-null="true" but you may not have set the NOT NULL flag in the database. This might have the effect of allowing the save to the db to occur but throw an NH warning/exception that you are trying to save the Physical Object without instantiating the Employee property.

HTH,

-devon


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 12, 2005 3:21 am 
Beginner
Beginner

Joined: Fri May 20, 2005 5:06 am
Posts: 28
1.) Thank you all.
2.) I found the error.
3.) It was my fault :oops:

As I told you the user has to select the Employee. This is done via a CombBox, which I filled with all Employees. So far, so good. But... the ComboBox was not the normal one, but one I created (it inherits the normal one). The only feature I added was, that if I bind a list to the box, that it can also show a null value. To achieve that, I created a new empty object at the databinding. I used the box with NHibernate on many places in my program and had never a problem with it. I don't know exactly why it was a problem now, but this was definitly the source of my error.

So thanks again and sorry for blaming NHibernate . :roll:


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.