简体   繁体   中英

How to protect SqlDataReader from multiple access in C#

I had a multi-threaded TCP server software written in C#. Many of the threads should read from database and i am using SqlDataReader for reading from database. When one thread wants to read from database, there is no problem but when two or more threads want to read from database, this situation starts to be a problem. .NET gives this exception: There is already an open DataReader associated with this Command which must be closed first.

How can i prevent from the error? How can i protect SqlDataReader from multiple access? Is mutex appropriate for this problem?

How can i protect SqlDataReader from multiple access?

Don't even share the connection.

Create a new SqlConnection for each database operation (in a using statement to dispose it at the end of the operation), and let the connection pool handle making this efficient.

If you're not sharing the connection, you won't end up with this error, and you won't be serializing your database access via locking.

You should be asking the .net runtime for a new sql connection inside each thread. This is the optimum solution as far as speed goes (this uses .net's sql connection pool so you don't loose time establishing connections).

I suggest creating a new connection per request instead of trying to re-use an existing active connection. I assume you are using some sort of class member or static reference to the connection, instead make it method scoped:

private void RespondingToTcpRequest()
{
    using (var connection = new SqlConnection(""))
    using (var command = new SqlCommand("", connection))
    {
         connection.Open();

         using (var reader = command.ExecuteReader())
         {
             // No locks or sharing issues here!
         }
    }
}

If I had some sample code demonstrating what you currently have, I could adapt that idea for your situation.

As for locking, if you really want to go down this route (seriously, don't ), all you need to do is lock (one of the basic synchronisation primitives):

private static readonly object ReaderLock = new object();

private void RespondingToTcpRequest()
{
    lock (ReaderLock)
    {
        // database connection, command, reader stuff here.
    }
}

A mutex won't necessarily be required as the problem will be process-local, where the lock keyword will suffice. Again, seriously, don't .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM