This project is read-only.

Lazy loading?

Apr 23, 2013 at 4:16 AM
Is there a standard way to express a lazily loaded object using NDatabase? I can certainly implement this manually, but was wondering if there was a standard mechanism in place for this.

The problem I'm solving is that I have a potentially unbounded revision history, but I'm only operating on a small subset of that history at any given time. A lazily loaded reference is a natural solution.
Apr 29, 2013 at 8:17 AM
simple answer is no.

More sophisticated:

Regarding lazy loading, NDatabase is focused on delivery of real objects with the same state as it was stored. In this simple concept, there is no place for lazy loading. Introducing any proxies will complicate the code significantly, and managing it properly could be error prone.

Going further, circular dependencies are handled well, and you are receiving exactly the same object as you stored.

Apr 29, 2013 at 3:04 PM
I wasn't thinking of proxies, but rather something like a Lazy<T>:
public Revision
    Lazy<Revision> previous;
    public Revision Previous
        get { return previous.Value; }
So NDatabase could recognize the special Lazy<T> type and defer the loading of these fields.

In any case, perhaps you have better suggestion to solve the actual problem. I have a very large tree structure representing a git-like revision history. At any given time, I'm generally only working with one or two revisions, so how would you represent this so NDatabase doesn't load the entire revision graph?
Apr 29, 2013 at 3:17 PM
If you have class A, which has field of type B, then you could query for B objects with some constraints to filter the result. Is that not enough for you?
Apr 29, 2013 at 3:24 PM
Suppose this is the class:
class Revision
   public Revision Previous { get; private set; }
Now suppose I have 50,000 revisions, and I want to access revision number 40,000 and fork it. Won't NDatabase load all 40,000 revisions which are all accessible via the Previous property?
Apr 29, 2013 at 3:32 PM
For this case, you are right, whole structure will be loaded and there is no way to improve it.

The redesign of class could help to improve that, so having some Node which reference to actual Revision and next / previous Node could allow you on loading Revision by query without all tree structure (which will be held by Nodes).
May 3, 2013 at 8:47 PM
Going back to the topic, if you are interested in lazy loading on the query result level, you could use IQuery method:
  • IObjectSet<T> Execute<T>(bool inMemory) where T : class; -> set in memory to false.
Additionally, you could use paging for the result set:
  • IObjectSet<T> Execute<T>(bool inMemory, int startIndex, int endIndex) where T : class;
Let me know, if this level of lazy loading will solve your issue.

May 9, 2013 at 4:22 PM
I think the only way to fully resolve the issue is to provide some hooks to customize serialization. Then I could write a custom Lazy<T> that was aware of the NDatabase API and could load results on demand. I did submit a ticket, so hopefully you'll get to it at some point.

The restructuring by splitting the class might work. The only problem is that the current structure is designed for high-performance in the most common scenario, and doesn't have any notion of persistence and isn't tied to the durability API which is provided in a separate extension (and uses NDatabase). Perhaps if NDatabase recognized [NonSerialized] instead of its own NonPersistent attribute, the class restructuring could work.

Thanks for the suggestions!