3

I want to avoid generating duplicate numbers in my system.

CreateNextNumber() will:

  1. Find the last number created.
  2. Increment the value by one.
  3. Update the value in the database with the new number.

I want to avoid two clients calling this method at the same time. My fear is they will pull the same last number created, increment it by one, and return the duplicate number for both clients.

Questions:

  1. Do I need to use single mode here? I'd rather use Per Call if possible.
  2. The default concurrency mode is single. I don't understand how Per Call would create multiple instances, yet have a single thread. Does that mean that even though multiple instances are created, only one client at a time can call a method in their instance?
Mike
  • 2,912
  • 4
  • 31
  • 52

3 Answers3

2

If you use InstanceContextMode.Single and ConcurrentcyMode.Single your service will handle one request at a time and so would give you this feature - however, this issue is better handled in the database

Couple of options:

  1. make the field that requires the unique number an identity column and the database will ensure no duplicate values
  2. Wrap the incrementing of the control value in a stored procedure that uses isolation level RepeatableRead and read, increment and write in a transaction

for your questions you might find my blog article on instancing and concurrency useful

Richard Blewett
  • 6,089
  • 1
  • 18
  • 23
0

Single instance will not stop the service from handling requests concurrently, I don't think. You need a server side synchronisation mechanism, such as a Mutex, so that all code that tries to get this number first locks. You might get away with a static locking object inside the service code actually, which will likely be simpler than a mutex.

Basically, this isn't a WCF configuration issue, this is a more general concurrency issue.

private static object ServiceLockingObject = new object();

lock (ServiceLockingObject)
{
   // Try to increment your number.
}
Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
  • Well concurrency mode is single by default. My understanding is that single instance + single concurrency = only one thread that clients access in a queue. – Mike Jul 15 '11 at 14:23
  • You could be correct there, apologies but my WCF configuration knowledge is limited. A useful test of this would be to have a service method with a long sleep time and make two client calls to it, time how long it takes to get to the second call. – Adam Houldsworth Jul 15 '11 at 14:25
0

Don't bother with WCF settings, generate unique numbers in the database instead. See my answer to this question for details. Anything you try to do in WCF will have the following problems:

  • If someone deploys multiple instances of your service in a web farm, each instance will generate clashing numbers.
  • If there is a database error during the reading or writing of the table, then problems will ensue.
  • The mere act of reading and writing to the table in separate steps will introduce massive concurrency problems. Do you really want to force a serializable table lock and have everything queue up on the unique number generator?
  • If you begin a transaction in your service code, all other requests will block on the unique number table because it will be part of a long-running transaction.
Community
  • 1
  • 1
Christian Hayter
  • 30,581
  • 6
  • 72
  • 99