-->
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.  [ 1 post ] 
Author Message
 Post subject: Making complex batch insertions more robust...
PostPosted: Thu Jan 18, 2007 12:39 am 
Beginner
Beginner

Joined: Thu Dec 08, 2005 6:49 pm
Posts: 49
I'm in a unique position whereby I am using NHibernate in a winforms application that exposes its domain objects through a kind of application automation API (think Word.Application, for consumption by macros, scripts and add-ins, etc).

Since my database schema is quite complex, I have exposed a transaction API so that scripters don't need to worry so much about nasty foreign key exceptions if they accidentally attach entities in the wrong order (since all the entities will be batched).

My problem is that when an entity has multiple parents who themselves have parents is inserted, the internal batch insertion queue is not in the appropriate order. For example, the insertion of [Child] in the schema below:

Code:
LeftGrandParent -< LeftParent -< Child >- RightParent >- RightGrandParent

Could result in the following insertion queue:

LeftGrandParent
RightGrandParent
Child
LeftParent
RightParent

As you can see, the insertion of [Child] will fail since the [LeftParent] and [RightParent] foreign entities wont exist in the database yet.

The usual solution to this is to simply commit the parents before the child in a separate transaction. But as I said, I'm trying to hide such implementation details from my potential scripters.

To temporarily get around this problem, I have made a small change to the SessionImpl.ExecuteAll() method whereby it loops through the insertions over and over (ignoring any exceptions) until either all of them work or none of them work (just like the YAST2 installer). If it gets to a stage where none of the executions succeed, it raises the first exception encountered.

Is there a cleaner way to go about this?
If not, is this useful enough to warrant a feature request?
Does it look like the the simple patch below could break anything (all the unit tests still succeed)?


Cheers,
Nathan


Code:
Index: SessionImpl.cs
===================================================================
--- SessionImpl.cs    (revision 2568)
+++ SessionImpl.cs    (working copy)
@@ -3238,12 +3238,44 @@

  private void ExecuteAll(IList list)
  {
-     foreach (IExecutable e in list)
-     {
-         Execute(e);
-     }
-     list.Clear();
+     int count = list.Count;

+     while (count > 0)
+     {
+         bool allFailed = true;
+         Exception firstException = null;
+
+         for (int i = 0; i < count; i++)
+         {
+             try
+             {
+                 Execute((IExecutable)list[i]);
+                 list.RemoveAt(i);
+                 i--;
+                 count--;
+                 allFailed = false;
+             }
+             catch (Exception ex)
+             {
+                 if (firstException == null)
+                 {
+                     firstException = ex;
+                 }
+             }
+         }
+
+         if (allFailed)
+         {
+             throw firstException;
+         }
+     }
+
      if (batcher != null)
      {
          batcher.ExecuteBatch();


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

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.