The proxy method you describe is how I have implemented the data
virtualization.
However, I do not use a conversation to hydrate the objects, I create
a new SessionScope for each group I need to load.  I did not want to
use a conversation because, from what I understand, every object
loaded in the conversation will remain in the first level cache for
the life of the conversation.  If the user ended up scrolling around
and displayed the entire tree, then the entire tree would be in the
first level cache.  This would use much too much memory and defeat the
purpose of the data virtualization.

As for your argument against auto-eviction.  We don't need to do the
reference counting ourselves.  That is what the garbage collector does
best.  When an object gets old you just change the reference in the
cache to a weak reference.  When nothing in the user code holds a
reference to the object, it will get GC'd in due time.  In the mean
time, the object in the cache will act as normal.
The only sticky point I see off the top of my head is that you never
want a weak reference in the cache to an object that has been updated
by the user, but not flushed.  The user code could modify the object,
then drop it's reference before the object is flushed to the DB.  I
don't yet know enough about the NH code base to be able to tell if
this is a big issue or not, but I am guessing it is not.
>From what I understand, this is the primary problem with using long-
running sessions.  So, fixing this seems like a big win, at least for
the desktop world.


I ran into another issue with NH object proxies.  They do not appear
to be compatible with WPF.  Specifically WPF bindings can not access
the actual data through a NH proxy (as created when you set an AR
class as lazy).  I have added a Self method to my AR base class that
simply does, "return this;".  That gets a reference to the true
object, which does work with WPF bindings.  So, for now, every binding
to a lazy object is going through this Self method.  But I am not
happy about it.
The only reason I am using lazy objects is because I can not get a
BelongsTo reference to lazy load.  If anyone else has gotten a lazy
BelongsTo, I would love to hear how.

-Dan

On Jul 24, 8:00 am, Markus Zywitza <[email protected]> wrote:
> Hi Dan
>
> for your tree, I recommend a manual proxy that only has the tree
> structure information and the  id of the object it represents. You can
> then load all proxies in one go:
>
> using (new SessionScope())
> {
>   foreach(var item in TreeItem.FindAll())
>   {
>     tree.Add(new TreeItemProxy(item));
>   }
>
> }
>
> then you create the IConversation and everytime an object should be
> loaded, it as easy as
>
> conversation.Execute(
> ()=>displayItem(TreeItem.Find(selectedTreeItemProxy.itemId)));
>
> As for auotmatic evicting old references:
>
> This is a source for hard to find bugs. Within a session or
> conversation, changes to an entity are tracked automatically. Imagine
> an object being unused for a lot of time and automatically evicted
> some time later. Then the code changes it and those changes will never
> make it to the DB. You have to do reference counting to circumvent
> this and such isn't simply worth the effort.
>
> The problem with lazy loading is that NH-generated proxies keep a
> reference to the ISession used for originally loading the proxied
> object. If you change NH to allow reattaching, lazy loading is a
> no-brainer for AR because we can create sessions on demand if there is
> none open through a scope or conversation.
> It boils down to creating NHibernate.ByteCode.ActiveRecord. I started
> such a project once, but I didn't get any workable results, mainly
> because the session storage implementation in an abstract NH class
> used by the bytecode providers is not virtual (grr). If you want to
> try yourself: Good Luck!
>
> -Markus
>
> 2010/7/20 Dan Jasek <[email protected]>:
>
>
>
> > Thanks for the reply.  Sorry I'm getting back to this late.
>
> > You mention that a detached object is temporarily attached for DB
> > operations.  Can you give an example of a circumstance when this would
> > happen.  I can't find any mention of re-attachment in the
> > documentation or code.  From what I understand of NH, the only time an
> > object needs to perform DB operations is in a lazy scenario.  And as
> > you mentioned, these just throw exceptions instead of attempting a re-
> > attach.
>
> > I seem to be able to use detached objects with lazy loading OK.  I
> > just re-attach them to a session when I access something that may not
> > yet be hydrated.  It would be nice if AR did this automatically
> > though.  This is the method I wrote to do this:
> > public void Reattach() {
> >            if (!holder.ThreadScopeInfo.HasInitializedScope)
> >                throw new Exception("Cannot reattach AR object.  No
> > open Scope.");
> >            holder.CreateSession(typeof(T)).Lock(this,
> > NHibernate.LockMode.None);
> >        }
>
> > The only problem with it is that it will throw an exception if the
> > object is already attached to a session.  That is why I asked about
> > detecting if an object is currently attached to a session.  I would
> > like to add a check before I attempt the re-attachment.  But looking
> > deeper into NH, I don't think it is currently possible.  It looks like
> > the proxy infrastructure is a little too transparent.  You are unable
> > to ask this sort of meta-questions about NH objects.
>
> > If anyone is interested in my project:
> > I will be going with AR for my project.  The maturity, performance and
> > features of NH coupled with the ease of use of AR make it a pretty
> > easy choice.  There are definitely some warts however, neither project
> > was designed for the peculiarities of GUI use.  I guess the desktop
> > jockeys are not as cool as the web dudes anymore.
>
> > As I mentioned before, my primary concern is the display of a large
> > tree structure in a list view which supports data virtualization.  I
> > have decided to simply use detached objects for this.  There should
> > not be any lazy loading issues with this particular implementation.
> > The data virtualization is handled by light-weight proxy objects that
> > know the identity of the AR object that they wrap.  Once the proxy
> > objects are generated there will be no need to walk the tree.
> > So, the only issue is stale detached objects.  To solve this, I keep a
> > list of currently displayed objects and re-load them when required.
> > The OnUpdate hook makes this relatively easy.  No other process will
> > access this DB, so only local mods need to be accounted for.
>
> > This is not exactly ideal in my mind though.
> > So far, there are two additions I could use to AR and NH:
> > Automatic handling of re-attaching detached objects for lazy
> > operations.  I can understand why AR does not do this.  It looks like
> > it would require changes to NH, and custom implementations of the
> > collection proxies.
>
> > The option of a different first level cache.  For web applications,
> > the build up and tare down of the sessions and their cache must be as
> > fast as possible and take as few resources as possible.
> > But in a GUI app I am willing to trade resources and speed for
> > additional management features.  These features would include:
> > * Setting cache size and age targets.
> > * Monitoring object references.
> > * Auto-eviction of old and unused objects.
> > * Recovery from failed sessions.
>
> > Once I get more familiar with the code base, I may try to put some of
> > these pieces in place...
>
> > -Dan
>
> > On Jun 4, 7:31 am, Markus Zywitza <[email protected]> wrote:
> >> Inline:
>
> >> Dan Jasek <[email protected]>:
>
> >> > Is there a hook I can connect to to detect when a session has failed?
>
> >> If you are using IConversation, then it has an extension point for it as
> >> shown in the docs.
>
> >> > Also, is it possible to determine if an AR object is attached to an
> >> > active session or not?  I looked through the documentation but didn't
> >> > see a way.
>
> >> Depends. Without conversations or scopes,every AR object is always detached
> >> and will be only temporarily attached for DB operations. Those detached
> >> objects however don't support lazy initialisation. You can however use a
> >> non-lazy-class for detached operations and a lazy class for attached
> >> operations that map to the same table.
>
> >> Using conversation per modification could work.  If I did this, I> don't 
> >> think there would be any advantage to keeping the read-only
> >> > display objects in a conversation (I don't need to traverse the web at
> >> > this point).  I could just leave them as detached...
>
> >> Not if you need lazy-loading and you will need it when you have a single 
> >> web
> >> of objects. See above for reasons.
>
> >> Maybe I could periodically clean the cache myself.  It looks like> 
> >> NHibernate keeps the cache internal, however.  Do you know of a way to
> >> > get to it?
>
> >> No, but you might want to ask that question at the nh-users list.
>
> >> -Markus
>
> > --
> > You received this message because you are subscribed to the Google Groups 
> > "Castle Project Users" group.
> > To post to this group, send email to [email protected].
> > To unsubscribe from this group, send email to 
> > [email protected].
> > For more options, visit this group 
> > athttp://groups.google.com/group/castle-project-users?hl=en.- Hide quoted 
> > text -
>
> - Show quoted text -

-- 
You received this message because you are subscribed to the Google Groups 
"Castle Project Users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/castle-project-users?hl=en.

Reply via email to