views:

1135

answers:

2

I am working on a large application that manages complex 'events' with quite a bit of data.

The application is broken into a client (C# mainly .NET 2.0 mainly), a WCF based server made to run on IIS (web services at this layer), and a data back end that is NHibernate based with an MS SQL Server database backend.

We are encountering a bug with the follow scenario:

Multiple users (in this case 6, in our testing) simultaneously save a persisted object (such as an event) on the client. (This is done via a verbal countdown, so we're talking a second or so difference due to reaction times)

When they save objects on the client, the client calls the server to save that object. The server does any business logic required, and then commits the change via NHibernate.

In this situation (multiple saves over service calls) some clients will come back with an unhanded exception:

"Row was updated or deleted by another transaction"

Which is an NHibernate exception.

In my research I found some instances of this error, but it was always sequential. Our application is fine sequentially, this only happens with simultaneous saves.

How should multiple simultaneous NHibernate transactions be protected from each other?

(This is going to be a high volume application, so minimal needed locking is good. We can't afford to lock all saves generally.)

Are there NHibernate settings that would do this? Do we need to figure out some server code side locking before hand? Can the database handle this with perhaps with different transaction protection settings?

This is a bear to test, like most threading issues, hence the research/theory approach. What is the experience with an architecture like this?

Edit: Further information and a theory.

It seems that changing values that are directly in the table as the main entity did not cause this problem, while changing elements that are accessed through a join did. (In this case a set of attributes).

Our working theory that seems to fit this situation is the following:

Multiple saves come in for the same event. Each one gets a copy of the existing event (to modify). The first ones to save are OK. The later ones, however, have updates such as the addition or deletion of attributes (which are a join table) and discover that the add or delete that needs done has already been done, and bails out because another transaction edited the event.

How should we keep these events in sync?

+1  A: 

I had the same problem with a single user app which was multithreaded. The key was to decorate my session variable with [ThreadSafe]. Oddly the various session managers I've looked at don't seem to do this, and they reckon they're thread safe automatically ... wasn't the case in my experience.

Asp Session Manager

Multi DB Session

MrTelly
A: 

I accepted the above answer because it was more or less the route we went with. I wanted to elaborate further. Our application is intended to be used heavily, so locking a 'update major entity' procedure outright is a bad idea.

What we ended up doing was using the C# mutex that took "something uniqueish" to lock with, in this case an event ID. This means that any operations on the same complex entity would be locked, and become 'atomic' in that sense. This fixed our problem. We wrapped every 'destructive' service operation in a mutex more or less (through an existing utility class).

Colin Dabritz