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.  [ 13 posts ] 
Author Message
 Post subject: Help with Session and Flushmode
PostPosted: Fri Jul 28, 2006 12:04 pm 
Newbie

Joined: Fri Mar 24, 2006 4:46 pm
Posts: 13
I have a general question about usage and behavior of Session and session.SetFlushMode.

We are using NHibernate 1.2.0.1 and SQL Server 2000, with .Net 2.0 in an Asp.Net application.

We are currently migrating a large stored procedure based web application to NHibernate using a Domain model, etc.
We started investigating some poor performance in the time it takes one of our pages to load. The page is used for administration purposes in our application. The page in question has a object hierarchy attached to is somewhat like this

PageControl is the parent
it then has a child Page which is a lazy loaded many to One Collection hanging off of Page

The Page collection (meaning all pages, contains 681 members)
is loaded into a drop down so that the user can change the Page that is associated to the PageControl object

On page reload(f5) we have noticed that the Page Collection is being flushed and reloaded, is the only way to turn this off by manually setting the the FlushMode to commit for this page?

we would like to keep the underlying nhibernate implementation away from the page logic but if this is our only option we'll have to do it.

Thanks
Eric


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 28, 2006 12:45 pm 
Expert
Expert

Joined: Fri May 13, 2005 5:56 pm
Posts: 308
Location: Santa Barbara, California, USA
have you enabled the second-level cache on the Page collection? This would at least allow NH to check the cache before going back to the db. something like:
Code:
<class name="PageControl" ... >
   ...
   <bag name="Pages" ...>
      <cache usage="read-write" />
      <key column="PageID" />
      <one-to-many class="Page" ... />
   </bag>

</class>


-devon


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 28, 2006 1:55 pm 
Newbie

Joined: Fri Mar 24, 2006 4:46 pm
Posts: 13
Here is what my mapping looks like
Code:
<many-to-one name="Page" class="edited.Core.Domain.Page,edited.Core">
<column name="PageID" length="4" sql-type="int" not-null="true"/>
</many-to-one>


I have played with making the whole Page object cacheable in read-only mode and it doesn't seem to make a difference.

Any one else have any thoughts.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 28, 2006 2:02 pm 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
You would have to cache the query you use to retrieve the page list as well, since entity/collection cache only works for accesses by id.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 28, 2006 2:44 pm 
Expert
Expert

Joined: Fri May 13, 2005 5:56 pm
Posts: 308
Location: Santa Barbara, California, USA
post mapping files for PageControl and Page object. also, please post code you are using to load the PageControl object and populate the DropdownList. can be edited for brevity, no need to post everything.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 28, 2006 5:43 pm 
Newbie

Joined: Fri Mar 24, 2006 4:46 pm
Posts: 13
Actually we have kind of fixed the issue, we had done something like this in our collection properties to make development a little easier
Code:
public virtual IList<RequisitionToSupplier>RequisitionToSuppliers             {
                     get
                     {

                           return m_RequisitionToSuppliers;

                     }



Became…
Code:
public virtual IList<RequisitionToSupplier> RequisitionToSuppliers

{

                     get

{

                if(m_RequisitionToSuppliers == null)

{

                    m_RequisitionToSuppliers = newList<RequisitionToSupplier>();

}

                           return m_RequisitionToSuppliers;


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 28, 2006 6:07 pm 
Newbie

Joined: Fri Mar 24, 2006 4:46 pm
Posts: 13
This does beg the question, how is everyone else handling adding items to collections of new entities?
It would be nice to just do something like

ParentItem item = new ParentItem();
item.ChildItems.Add(new ChildItem());

but that doesnt work when a child collection is null which it is on a new object


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 29, 2006 12:29 am 
Expert
Expert

Joined: Fri May 13, 2005 5:56 pm
Posts: 308
Location: Santa Barbara, California, USA
Quote:
but that doesnt work when a child collection is null which it is on a new object

i don't think that is correct for an IList. I thought I remember reading somewhere that ILists do allow the addition of an element if the collection is null. Even so, I (needlessly) initialize the collection in my constructor:

Code:
class ParentItem {
  private int id;
  private IList childItems;

  public ParentItem() {
    this.id = -1;
    this.childItems = new ArrayList();
  }
}

and, when creating the Parent -> Child relationship:

Code:
ParentItem item = new ParentItem();
ChildItem child = new ChildItem();

item.ChildItems.Add(child);
child.ParentItem = item;

session.SaveOrUpdate(item);

actually, personally, i would change the constructor for the ChildItem to require the parent parameter (since the child cannot normally exist without the parent), thereby automatically setting both sides of the relationship:

Code:
ParentItem item = new ParentItem();
item.ChildItems.Add(new ChildItem(item));

session.SaveOrUpdate(item);

don't forget, you really do need to manage both sides of the relationship. especially once you start implementing the second-level cache. if you do not set both sides of the relationship and the second-level cache is in play, your cached items will not be updated properly.

-devon


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 29, 2006 3:28 am 
Newbie

Joined: Fri Mar 24, 2006 4:46 pm
Posts: 13
Actually we do manage both sides, my post was incomplete, sorry for any misunderstanding there.

The issue we were trying to address is that we seem to have create a new IList collection like so:
Code:
ParentItem p = new ParentItem();
p.Children = new List<Child>();
Child c = new Child();
c.Parent = p;
p.Children.Add(p);


It seems that when we add code like this in our Property getters

Code:
class Parent
{

    IList<Child> Children
    {
          get
          {
               if (m_Children == null)
               {
                     m_Children = new IList<Child>();
                }
                return m_Children; 
           }
           set
           {
                 //code
            }
     }
}


We have an issue where NHibernate thinks that all of our collections are dirty when we for instance reload a page. And if we have a page that has a ChildObject and we are loading a drop down with 600 possible Parent objects it can get expensive.
I think mostly I am trying to understand the behavior of the underlying implementation and the ramifications of doing things like this.

Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 29, 2006 3:36 pm 
Newbie

Joined: Fri Mar 24, 2006 4:46 pm
Posts: 13
we are using lazy loaded collections so we are unable to add logic to our constructor as it jacks up the initialization of the proxied objects.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 30, 2006 9:40 pm 
Expert
Expert

Joined: Fri May 13, 2005 5:56 pm
Posts: 308
Location: Santa Barbara, California, USA
hmmm, i guess they way we get around that is to have a private default constructor that can only be used by NH and an overloaded constructor that is exposed to the developers:

Code:
public class Parent {
   ...

   private Parent () {}

   public Parent(string title) {
      this.title = title;
      this.collection = new ArrayList();
   }
}

this way NH can initialize the entity while still leveraging lazily-loaded collections, but i can also guarantee that the collection is instantiated properly when a developer creates the entity in code.

-devon


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 31, 2006 2:05 am 
Newbie

Joined: Fri Mar 24, 2006 4:46 pm
Posts: 13
Great thanks for that tidbit.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 01, 2006 2:10 am 
Newbie

Joined: Fri Mar 24, 2006 4:46 pm
Posts: 13
actually Dynamic Proxy, and now NH (since 1.2) require the default constructor be public or protected, it complains if you try private.


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