4

How to use SqlTransaction in .net 2.0 so that when I start reading data from a table, that table is blocked for others (other programs) to read/write to that table?

If SqlTransaction is not a good option, than what is?

Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
This is it
  • 779
  • 2
  • 11
  • 23
  • Hi - I think this should happen by default as long as your database writes are inside a transaction and database reads are respecting those transactions, e.g. you don't allow dirty reads / you aren't using the with(nolock) hint... – Brandon Feb 16 '11 at 15:05
  • Sorry. I reread your question. If you want to block when reading than I think you might have to take out an update lock on your select, e.g. with(updlock). – Brandon Feb 16 '11 at 15:07

1 Answers1

7

This should be allowed by using Serializable transaction together with TABLOCKX hint in initial select statement. TABLOCKX should take exclusive lock on the table so nobody else can use that table and Serializable transaction should demand HOLDLOCK which means that all locks are kept until end of the transaction (you can use HOLDLOCK directly).

Update: I just tested different scenarios in Management studio and it looks like you do not need to explicitly use Serializable transaction. Using TABLOCKX within any transaction is enough.

Be aware that such approach can be big bottleneck because only one transaction can operate on such table = no concurrency. Even if you read and work with single record from million nobody else will be able to work with the table until your transaction ends.

So the command should look like:

SELECT * FROM Table WITH (TABLOCKX) WHERE ...

To use serializable transaction you can use SqlTransaction:

using (SqlConnection connection = new SqlConnection(connectionString))
{
  connection.Open();
  SqlTransaction transaction = connection.BeginTransaction(IsolationLevel.Serializable);

  try
  {
    ...
    transaction.Commit();
  }
  catch (Exception)
  {
    transaction.Rollback();
    ...
  }
}

Or System.Transactions.TransactionScope (default isolation level should be Serializable).

using (TransactionScope scope = new TransactionScope())
{
  using (SqlConnection connection = new SqlConnection(connectionString))
  {
    ...
  }
  scope.Complete();
}
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • Instead of using `SqlTransaction`'s constructor, you should use the `connection.BeginTransaction` method, so you end up with a transaction based on your connection. Otherwise, anything performed on the connection will not be encapsulated in the transaction. – Mark Avenius Feb 16 '11 at 15:28
  • @Mark: Thanks. I corrected it with some common SqlTransaction handling - I first wrote it in the same way as TransactionScope ... I also removed var constructs because question is about .NET 2.0. – Ladislav Mrnka Feb 16 '11 at 15:31