How would you guys handle an aggregate root with versioning? I.e. I have a object with a bunch of child objects. I want to change the child object, but I want to lock and version the parent object.

e.g.

class Post
{
  int Version;
  Comment[] Comments;
}

class Comment
{
  string Text;
}

using (session = new Session())
using (transaction = new Transaction())
{
  var post = session.Get<Post>(1);

  // This could happen automatically
  session.LockForUpdate(post);

  // Comments should be lazy loaded
  post.Comments[0].Text = "new text";

  // Notice, I save Post, not Comment.  Also,
  // this causes post.Version to become 
  // post.Version + 1.  Comment has no
  // version number and I've made no
  // explicit changes to post.
  session.Save(post);

  transaction.Commit();
}

This thread was imported from our support forum. The original discussion may contain more detailed answer. Original topic by dalroth.

asked Aug 16 '09 at 14:35

Editor's gravatar image

Editor
46153156157


One Answer:

1) Currently DO4 does not support versions. We're working on this now. This feature is related to many others (sync, disconnected state, global caching), thus it's of top priority for us. Later I'll publish a link to its full description in our issue tracker (must update the description based on latest discussions).

2) On the other hand, it never allow to propagate the state "through" subsequent transactions. So basically, this mean optimistic version checks is your own problem, but DO will ensure everything is properly locked.

Let's rewrite your code for DO:

using (Session.Open(domain))
using (var transactionScope = Transaction.Open())
{
  var post = Query<Post>.Single(1);
  // Post is already s-locked;
  // Session.Lock(LockMode.ForUpdate) isn't implemented yet,
  // but is already in our TODO list: http://code.google.com/p/dataobjectsdotnet/issues/detail?id=104
  // Note that "lock for update" is generally an optimization allowing to
  // minimize the amount of deadlocks. That's why we don't implement this ASAP.

  // If you want to make an optimistic version check here, currently you must use the following code:
  // This partially replaces lock for update.
  if (post.Version!=oldPostVersion)
    throw new OptimisticVersionCheckFailed(post, post.Version, oldPostVersion); // Will lead to rollback, see the tail.

  // We have correct post version now, and it is already s-locked.
  // Let's update it:
  post.Comments[0].Text = "New text"; // Comment is lazy loaded here

  // session.Save(post); // This shouldn't be done. DO tracks any changes automatically.

  transactionScope.Complete(); // This ensures transaction will be committed.
}

So as you see, we currently we expose any transactional state "as is". At any moment of time you can be sure that if you just read post.Version, it is the version from the storage fetched in current transaction, but not an outdated one. This is correct for any data you access through DO now.

On the other hand, right now we're working on mode allowing to violate this - i.e. it will allow you to use stale data, but in this case it will automatically run version checks on updates. So basically, DO will "know" what's valid, and what's stale. And if something is stale, version checks will be enforced for it automatically.

answered Aug 17 '09 at 08:59

Alex%20Yakunin's gravatar image

Alex Yakunin
29714412

Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

Subscription:

Once you sign in you will be able to subscribe for any updates here

Tags:

×573

Asked: Aug 16 '09 at 14:35

Seen: 2,183 times

Last updated: Aug 16 '09 at 14:35

powered by OSQA