-->
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.  [ 7 posts ] 
Author Message
 Post subject: Many-to-one - FK objects not refreshed after save
PostPosted: Fri Mar 03, 2006 8:24 am 
Newbie

Joined: Fri Mar 03, 2006 8:05 am
Posts: 14
This is my first time using NHibernate and all is going well except I have run into a problem where child objects are not being refreshed on a Save.

I have 2 tables, Event and EventCategory joined by a FK EventCategoryID. Here is my mapping file for the Event table:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="Business.Event, Business" table="Event">
<id name="Id" type="Int32" unsaved-value="0">
<column name="EventID" sql-type="int" not-null="true" unique="true" index="PK_Event"/>
<generator class="native" />
</id>
<property name="EventCategoryID" type="Int32" column="EventCategoryID" not-null="true"/>
<property name="Name" type="String" column="Name" not-null="true"/>
<many-to-one name="EventCategory" class="Business.EventCategory, Business" insert="false" update="false" cascade="all">
<column name="EventCategoryID" sql-type="int" not-null="true"/>
</many-to-one>
</class>
</hibernate-mapping>

And here is the mapping file for EventCategory:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="Business.EventCategory, Business" table="EventCategory">
<id name="Id" type="Int32" unsaved-value="0">
<column name="EventCategoryID" sql-type="int" not-null="true" unique="true" index="PK_EventCategory"/>
<generator class="native" />
</id>
<property name="Name" type="String" column="Name" not-null="true"/>
<bag name="Events" inverse="true" lazy="true" cascade="all-delete-orphan">
<key column="EventCategoryID"/>
<one-to-many class="Business.Event, Business"/>
</bag>
</class>
</hibernate-mapping>

When I save an Event, the data saves in the database fine, but a subsequent call to get all events has a null value for EventCategory. Am I doing something wrong?

Thanks for your help!


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 03, 2006 8:48 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Please post the code exhibiting the problem.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 03, 2006 9:59 am 
Newbie

Joined: Fri Mar 03, 2006 8:05 am
Posts: 14
I'm pretty sure I've overlooked some attribute in the mapping file and this is not a code related problem but here is the code that does the save:

tx = m_session.BeginTransaction();
m_session.SaveOrUpdate(item);
tx.Commit();

and here is my Event class:

public class Event : BusinessBase
{
#region Member Variables

protected int _Id;
protected int _eventCategoryId;
protected string _name;
protected EventCategory _eventCategory;

#endregion

#region Constructors

public Event() { }

public Event( string name, int lastModifiedBy, DateTime lastModifiedDate, int createdBy, DateTime createdDate, EventCategory eventCategory ) :
base(lastModifiedBy, lastModifiedDate, createdBy, createdDate)
{
this._name = name;
this._eventCategory = eventCategory;
}

#endregion

#region Public Properties

public override int Key
{
get { return this.Id; }
}

public int Id
{
get {return _Id;}
set { _Id = value; }
}

public int EventCategoryID
{
get { return _eventCategoryId; }
set { _eventCategoryId = value; }
}

public string Name
{
get { return _name; }
set
{
_name = value;
}
}

public EventCategory EventCategory
{
get { return _eventCategory; }
set { _eventCategory = value; }
}

#endregion


}


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 03, 2006 11:16 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Well, I was more interested in the code that creates the Event object and the code you use to determine that the field is null after saving.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 03, 2006 11:33 am 
Newbie

Joined: Fri Mar 03, 2006 8:05 am
Posts: 14
Code:
<asp:GridView
        ID="gridView"
        runat="server"
        AutoGenerateColumns="false"
        AutoGenerateSelectButton="true"
        AllowPaging="true"
        DataKeyNames="ID"
        DataSourceID="EventDataSource"
        SelectedIndex="0">
   <Columns>
   <asp:TemplateField HeaderText="Activity">
   <ItemTemplate>
   <asp:Label runat="server" ID="lblEventCategory" Text='<%# Eval("EventCategory.Name") %>'></asp:Label>
   </ItemTemplate>
    </asp:TemplateField>
   <asp:BoundField DataField="Name" HeaderText="Event" />
   <asp:BoundField DataField="LastModifiedDate" HeaderText="Last Modified" HtmlEncode="false" DataFormatString="{0:d}" ReadOnly="true"/>
   </Columns>
    </asp:GridView>
   
    <asp:detailsview
        id="detailsView"
        OnItemInserted="detailsView_ItemInserted"
        OnItemUpdated="detailsView_ItemUpdated"
        datasourceid="EventDetailDataSource"
        autogenerateinsertbutton="true"
        AutoGenerateEditButton="true"
        AutoGenerateDeleteButton="true" 
        autogeneraterows="false"
        datakeynames="ID"       
        gridlines="Both"
        runat="server">
        <Fields>
        <asp:TemplateField HeaderText="Activity">
            <ItemTemplate>
            <asp:Label runat="server" ID="lblEventCategory" Text='<%# Eval("EventCategory.Name") %>' />
            </ItemTemplate>
            <EditItemTemplate>
            <asp:DropDownList ID="lstEventCategoryEdit" SelectedValue='<%#  Bind("EventCategoryID") %>' DataValueField="ID" DataTextField="Name" DataSourceID="EventCategoryDataSource" runat="server">
            </asp:DropDownList>
            </EditItemTemplate>
            <InsertItemTemplate>
            <asp:DropDownList ID="lstEventCategoryInsert" SelectedValue='<%#  Bind("EventCategoryID") %>'  DataSourceID="EventCategoryDataSource"
            DataValueField="ID" DataTextField="Name" runat="server">
            </asp:DropDownList>
            </InsertItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="Name" HeaderText="Event" />
        <asp:BoundField DataField="LastModifiedDate" ReadOnly="true" InsertVisible="false" HeaderText="Last Modified" />
        </Fields>   
    </asp:detailsview>
                 
   <asp:ObjectDataSource
            ID="EventDataSource"
            runat="server"
            TypeName="BusinessFacade.EventFacade"
            DataObjectTypeName="Business.Event"
            SelectMethod="GetAll">
    </asp:ObjectDataSource>
   
   <asp:ObjectDataSource
            ID="EventDetailDataSource"
            runat="server"
            SelectMethod="GetById"
            InsertMethod="Save"
            UpdateMethod="Save"
            DeleteMethod="Delete"
            TypeName="BusinessFacade.EventFacade"
            DataObjectTypeName="Business.Event">
            <SelectParameters>
            <asp:ControlParameter ControlID="gridView" Type="Int32" Name="ID" PropertyName="SelectedValue" />
            </SelectParameters>
            <InsertParameters>
            <asp:ControlParameter ControlID="lstEventCategoryInsert" PropertyName="SelectedValue" Name="EventCategoryID" Type="Int32" />
            </InsertParameters>
            <UpdateParameters>
            <asp:Parameter Name="LastModifiedDate" Type="DateTime" />
            </UpdateParameters>
            <DeleteParameters>
            <asp:ControlParameter ControlID="gridView" Type="Int32" Name="ID" PropertyName="SelectedValue" />
            </DeleteParameters>
            </asp:ObjectDataSource>
   
   <asp:ObjectDataSource ID="EventCategoryDataSource" runat="server" SelectMethod="GetAll"
            TypeName="BusinessFacade.EventCategoryFacade"></asp:ObjectDataSource>
   


    public class EventFacade : BusinessFacadeBase
    {
        public EventFacade()
        {

        }

        public void Save(Event entity)
        {
            BaseDataAccess mgr = new BaseDataAccess();
            CheckObjectBeforeSave(entity);
            mgr.Save(entity);
        }

        public void Delete(Event entity)
        {
            BaseDataAccess mgr = new BaseDataAccess();
            mgr.Delete(entity);
        }

        public IList GetAll()
        {
            BaseDataAccess mgr = new BaseDataAccess();
            return mgr.Get(typeof(Event));
        }

        public Event GetById(int id)
        {
            BaseDataAccess mgr = new BaseDataAccess();
            return mgr.Get(typeof(Event), id) as Event;
        }

}


The DataAccess layer and NHibernate session management is implemented as http://blog.benday.com/archive/2005/03/16/198.aspx

Edit: I added code tags to preserve layout -- Sergey


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 03, 2006 12:08 pm 
Newbie

Joined: Fri Mar 03, 2006 8:05 am
Posts: 14
well I found a workaround which is to refresh the entity after doing a commit...but is this really necessary?

protected virtual void Save(object item)
{
ITransaction tx = null;

try
{
tx = m_session.BeginTransaction();

m_session.SaveOrUpdate(item);
tx.Commit();
m_session.Refresh(item);

}
catch (Exception ex)
{
if (tx != null) tx.Rollback();

throw ex;
}
}


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 03, 2006 3:24 pm 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
I still don't see where you set Event.EventCategory to something non-null. If you are expecting NHibernate to do it for you when setting Event.EventCategoryID, then don't - NHibernate doesn't do this (it only changes object fields on Refresh/Load, as you noticed). The best way would be to drop the EventCategoryID field and use only EventCategory reference, but I don't know if you can do this in the context of your application.


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