-->
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.  [ 3 posts ] 
Author Message
 Post subject: Problems with lazy fetching or problems with my head
PostPosted: Thu Dec 27, 2007 2:49 am 
Newbie

Joined: Wed Dec 12, 2007 12:41 am
Posts: 4
Location: Minsk, Belarus
Sorry for bothering, have met a problem I can not resolve by myself. I think the main reason - because I don't quite understand the way NHibernate works with Collections, but, documentation is readed from the beginning to the top. May be I have missed smth because of my English. Not quite sure.
My main problem is that I have not found a good source to read from about the way objects are handled by NHibernate. I am really new with ORM, so it is really hard form me.


The problem: Lazy Fetching or Mapping and Object initializing... not quite sure.

Mapping documents:
Assigment.hbm.xml
Trip.hbm.xml
Person.hbm.xml


I have 2 instances: Person and Trip. Their association is many-to-many, but, I need to have some additional properties of association so I have additional Table Assigment.
Here are my mappings:


Person.hbm.xml


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

  <class name="Model.Person" table="Person">
    <id name="Email" column="email" type="System.String">
      <generator class="assigned"/>
    </id>
    <property name="Name" column="name"  type="System.String"  />
    <property name="Password" column="password" type="System.String" />
    <property name="LastName" column="lastName" type="System.String"/>
    <property name="Sex" column="sex" type="System.String"/>
    <property name="City" column="city" type="System.String"/>
    <property name="Country" column="country" type="System.String"/>
    <property name="Address" column="address" type="System.String"/>
    <property name="Zip" column="zip" type="System.String"/>
    <property name="PicturePath" column="picturePath" type="System.String"/>
    <property name="Birthday" column="birthday" type="System.String"/>
    <property name="Info" column="info" type="System.String"/>   
    <property name="IsAdmin" column="isAdmin" type="System.Boolean" />
    <property name="Cellphone" column="cellphone" type="System.String"/>
    <property name="Link" column="link" type="System.String"/>
    <property name="TripStory" column="tripStory" type="System.String"/>
    <property name="BestBooks" column="bestBooks" type="System.String"/>
    <set name="Assigments" table="assigments" cascade="all" lazy="true">
      <key column="person_email"></key>
      <one-to-many class="Model.Assigment"/>
    </set>
  </class>
</hibernate-mapping>




Trip.hbm.xml
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Model">
  <class name="Model.Trip" table="trips" >
    <id name="Trip_id" column="trip_id" type="Int32">
      <generator class="native"/>
    </id>
    <property name="Name" type="System.String"/>
    <property name="City" type="System.String"/>
    <property name="Country" type="System.String"/>
    <property name="State" type="System.String"/>
    <property name="IsInvitingAllowed" type="System.Boolean"/>
    <property name="IsBringingAllowed" type="System.Boolean"/>
    <property name="StartDate" column="startDate" type="Date"/>
    <property name="EndDate" column="endDate" type="Date"/>
    <property name="Description" type="String"/>           
    <set name="AssignedPersons" table="assigments" cascade="all" lazy="true">
      <key column="trip_id"/>
      <one-to-many class="Model.Assigment"/>
    </set>
    <set name="Images" table="images" cascade="all">
      <key column="trip_id"/>     
      <element type="System.String" column="imagePath"></element>
    </set>
  </class>
</hibernate-mapping>



Assigment.hbm.xml
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Model">
  <class name="Model.Assigment" table="assigments" lazy="true">
    <id name="Id" column="id" type="Int32">
      <generator class="native"/>
    </id>
    <property name="Guests" type="System.String"/>   
    <property name="IsOwner" type="System.Boolean"/>
    <property name="IsActive" type="System.Boolean"/>
    <many-to-one name="Person" column="person_email" class="Model.Person" not-null="true" fetch="join" cascade="all"/>
    <many-to-one name="Trip" column="trip_id" class="Model.Trip" not-null="true" fetch="join" cascade="all"/>
  </class>
</hibernate-mapping>


I have gotten 1000s of errors, but, after resolving all of them, I got the next one:

Full stack trace of any exception that occurs:
[SqlException (0x80131904): Cannot insert the value NULL into column 'person_email', table 'TripInviteDB.dbo.assigments'; column does not allow nulls. UPDATE fails.
The statement has been terminated.]
System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) +862234
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +739110
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) +188
System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +1956
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +149
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +903
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +132
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) +415
System.Data.SqlClient.SqlCommand.ExecuteNonQuery() +135
NHibernate.Impl.BatcherImpl.ExecuteNonQuery(IDbCommand cmd) +29
NHibernate.Persister.Collection.AbstractCollectionPersister.Remove(Object id, ISessionImplementor session) +380

[ADOException: could not delete collection: [Model.Person.Assigments#fly_fuzz@tut.by]]
NHibernate.Persister.Collection.AbstractCollectionPersister.Remove(Object id, ISessionImplementor session) +553
NHibernate.Impl.ScheduledCollectionRemove.Execute() +32
NHibernate.Impl.SessionImpl.Execute(IExecutable executable) +112
NHibernate.Impl.SessionImpl.ExecuteAll(IList list) +72
NHibernate.Impl.SessionImpl.Execute() +198
NHibernate.Impl.SessionImpl.Flush() +42
NHibernate.Transaction.AdoTransaction.Commit() +160
TripInviteControl.saveOrUpdate(Object o) in C:\Sites\TripInviteASPDev\App_Code\TripInviteControl.cs:159
register_permissions.Next4_Click(Object sender, ImageClickEventArgs e) in C:\Sites\TripInviteASPDev\register_permissions.aspx.cs:75
System.Web.UI.WebControls.ImageButton.OnClick(ImageClickEventArgs e) +105
System.Web.UI.WebControls.ImageButton.RaisePostBackEvent(String eventArgument) +115
System.Web.UI.WebControls.ImageButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +7
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +11
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +33
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5102




Here is the code I use to work with my objects.

Code:
Person p = (Person) Session["Person"]; //Person have been saved to DB                    //before
            Assigment assigment = new Assigment();
            assigment.Person = p;
            assigment.Trip = trip;
            assigment.IsOwner = true;
            assigment.IsActive = true;
            try
            {
                p.Assigments.Add(assigment);           
            }catch (Exception ex)
            {
                HashedSet hs = new HashedSet();
                hs.Add(assigment);
                p.Assigments = hs; 
            }
             
                     
            TripInviteControl.saveOrUpdate(p); //standard session opening from singleton and transaction stuff


And another thing I don't understand, why the testing code, which is
Code:
Trip t = new Trip();
        t.Name = "testxxx";
        t.IsBringingAllowed = false;
        t.IsHistoryEnabled = false;
        t.IsInvitingAllowed = false;
       
        Person p = new Person();
        p.Email = "testxxx1@test.com";
        p.Name = "yo!";
        p.Password = "sdf";

        Assigment asg  = new Assigment();       
        asg.Trip = t;
        asg.Person = p;
        asg.IsOwner = false;
        asg.IsActive = false;


        p.Assigments = new HashedSet();
        p.Assigments.Add(asg);
        TripInviteControl.save(p);


works just fine ???
But, if I don't handle the
Code:
try
            {
                p.Assigments.Add(assigment);           
            }catch (Exception ex)
            {
                HashedSet hs = new HashedSet();
                hs.Add(assigment);
                p.Assigments = hs; 
            }

and just p.Assigments.Add(assigment) I got a lazy fetching exception?


I am really lost. Appreciate any help.
Thank you for reading.
[/b]


Top
 Profile  
 
 Post subject: May be just some literature I can read?
PostPosted: Thu Dec 27, 2007 2:50 am 
Newbie

Joined: Wed Dec 12, 2007 12:41 am
Posts: 4
Location: Minsk, Belarus
I don't know where to look for. Don't have ability to buy one from Amazon.


Top
 Profile  
 
 Post subject: Re: Problems with lazy fetching or problems with my head
PostPosted: Thu Dec 27, 2007 1:20 pm 
Expert
Expert

Joined: Fri May 13, 2005 11:13 am
Posts: 292
Location: Rochester, NY
Thanks for a well-formatted question.

It looks like two problems. The first (NULL FK error) is related to a poorly set up bidirectional association. You have cascades going both directions from Person and Trip. It kind of looks like you have a Parent-Child relationship from both to your assignment class, in which case you'll need to invert the collections (use inverse="true" on your set mappings). You might also investigate managing the association objects as part of a
composite-element on either Person or Trip (if that makes sense in your domain model).

The lazy initialization error is happening on add because a set needs to be able to compare the new addition to existing elements, since a new one can be added only once. This requires the collection to be loaded, possibly lazily. You are getting the exception because the session the Person was loaded in has been closed. Your workaround is pretty ugly, since exception handling is very expensive, and adding a new collection instead of loading the existing one could mess with existing children.

There are several options: keep the session open so that the lazy loading functions, eagerly fetch the collection at load time, or use a bag instead (which doesn't need to be loaded on Add() operations). For collection behavior, http://www.hibernate.org/hib_docs/nhibe ... ollections and http://www.hibernate.org/hib_docs/nhibe ... tions.html


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 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.