chobo2
chobo2

Reputation: 85785

Get last value with nhibernate?

I have an int column for each revision I make of an item. I want to get the last revision number for that item and increment it by one and save it to this new revision I am making.

I am a bit concerned that I will run into a issue where the same item is being revised at the same time and all of a sudden I got 2 revisions with the same number.

Example

Item1  Revision 1
Item1  Revision 2
Item2  Revision 1
Item2  Revision 2
Item3  Revision 1

the above may already be in my database. Now I want to add another revision to Item1. It should be Revision "3".

I want to find that Item 1 had a last revision of "2" and then use that to figure out tit should be revision "3".

I am worried though that multiple people will start revision Item 1 and submit around the same time and that I will get revision 2 back in memory for all 3 people revising Item 1 and I will end up with

Item1 Revision 1
Item1 Revision 2
Item1 Revision 3
Item1 Revision 3 (should be 4)

Upvotes: 1

Views: 329

Answers (2)

Oskar Berggren
Oskar Berggren

Reputation: 5629

Create a unique key over the combination of primary key and revision number. That will at least prevent duplication in the DB.

The remaining issue is if you expect this parallel edit to happen often - if so you would probably want to add some mechanism to detect it earlier to save on user time. One method is to use pessimistic locking on the original row.

Upvotes: 0

Radim Köhler
Radim Köhler

Reputation: 123861

EDIT: 1) In case of updating the same row

There is an NHibernate feature: the Version or Timestamp property and the powerful management arround it. Try to read here: When to use Nhibernate ? for more details. Extract

...entity instance has a version, which can be a number or a timestamp. Hibernate increments an object’s version when it’s modified, compares versions automatically, and throws an exception if a conflict is detected. Consequently, you add this version property to all your persistent entity classes to enable optimistic locking. ... The version number is just a counter value—it doesn’t have any useful semantic value.

NHibernate documentation:

So, when you will use Version you will gain:

  • NHibernate will increment the Version value.
  • If someone is trying to update row with Version value which is old, stale... StaleException will be thrown.
  • you can append handler to solve this issue, this is up to your code.

You can then use more standard features (e.g. Interceptors) and audit all changes on update into different table... with the current Version number.

Summary: Versioning system in NHibernate will not solve everything. You will be provided with StaleExceptions... and have to handle them. BUT, you can be sure, that only one Version at time was stored with the same Version number

EDIT: 2) tracking new change as the new row

Please, take this as a suggestion, based on our approach. This is how we are implementing changes as a Audit tracking system

The business object e.g. IAuditable is defined as:

public class Article : IAuditable
{
  public virtual int ID { get; set; }
  public virtual string Text { get; set; }
  ...
  // if possible to move it to base for more Business Objects
  // public virtual IList<IHistory> History { get; set; }

  public virtual IList<ArticleHistory> History { get; set; }
}

Whenever There is an update, the Article itslef is updated, and new ArticleHistory instance is created. Using HiLo generator for its ID, it is correctly inserted even in a web-farm.

This approach allows to work with up-to-date instance of Article, improve performance (History is in separated table) and supports AOP (history tracking is turned on/off via Injecting the AuditAOPFilter. Only on a detail we load the History collection.

This is an suggestion. I can understand that this does not suite to your scenario (and does not answer the question).

Upvotes: 1

Related Questions