What happens if I call Thread.Abort() (in C#/.NET) on a thread that is currently executing an ODBC Command (specifically against MSSQL and Oracle, but also generally)? Will the command get cancelled? Will the DB server recognize there's nothing at the other end of the connection and kill the process (again, specifically MSSQL and Oracle)? Or do I need to explicitly call Cancel() on the connection first?
My goal is to ensure the safety of the database I'm connecting to if the worst should happen to my application (or the worst that I can catch and respond to, like system shutdowns etc).
I'd like to program defensively and try to issue a Cancel() if at all possible, but I'd like to know the behavior anyway.
If you want to ensure cancelling the SQL command, why not to use the TransactionScope.Dispose() method or simply do not Complete the transaction? It works above Thread, Process and such abstractions, and there will be no races between Thread cancelling and SQL command.
Also, as was stated in comments, your SQL driver can work in other Thread and can even be an unmanaged code, so the cancelling the Thread will not affect the SQL command, and you really need to Cancel() your connection or command.
Related
I'm confused about the behavior of this command:
SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess)
I would ideally like to start the query running and as soon as SQL server starts returning results, start processing them. This is as opposed to waiting for all results to be returned by SQL Server. It appears like this could speed up my program by about 40% given when SQL Server Management Studio starts returning results for my query.
It appears that it should be possible and some places such as this seem to indicate that it is.
I'm new to async programming, however, it seems to me like that command is calling the reader, spinning off a separate thread to do it, then waiting for the ExecuteReader to finish, which then returns a finished SQLDataReader.
Meaning that command is exactly equivalent to this without async:
SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess)
Or does the SQLDataReader returned from ExecuteReader naturally support streaming and only wait long enough for the stream to be available before returning? Does it work whether or not I call ExecuteReader vs ExecuteReaderAsync?
Thanks in advance!
however, it seems to me like that command is calling the reader, spinning off a separate thread to do it, then waiting for the ExecuteReader to finish, which then returns a finished SQLDataReader.
You are wrong. What async methods are supposed to do is start an operation, "pause" the execution of current method, freeing up the current thread, and, after the operation becomes available, restore the state machine and call the rest of method.
Connecting to SQL server is an I/O operation, which should be run in asynchronous mode, because you don't really need a .Net thread for this operation. After connection is open, both synchronous and asynchronous reader will behave exactly the same - as normal .Net classes.
Comparing to synchronous version of this method you'll got one free thread at a time of connecting to the SQL server and a small overhead for a state machine.
It is a .Net application which works with an external device. When some entity (corresponds to the row in a table) wants to communicate with device, the corresponding row in the SQL Server table should be locked until the device return a result or SQL Server times out.
I need to:
lock a specific row in a table so that row could be read, but could not be deleted or updated.
locking mechanism should run in a separate thread so that application's main thread works as usual
lock should be released if a response has made
lock should be released after a while if no response is received
What is the best practice?
Is there any standardize way to accomplish this?
Should I:
run a new thread (task) in my C# code and begin a serializable transaction, select desired row transactionally and wait to either time is up or cancellation token is received?
or use some combination of sp_getapplock and ...etc?
You cannot operate on locks across transactions or sessions. That approach is not feasible.
You need to run one transaction and keep it open for the duration that you want the lock to persist.
The kind of parallelism technology you use is immaterial. An async method with async ADO.NET IO would be suitable. So would be a separate LongRunning task.
You probably need to pass a CancellationToken to the transaction code that when signaled makes the transaction shut down. That way you can implement arbitrary shutdown conditions without cluttering the transaction code.
Here's few points that you should consider:
Sp_getapplock is not row based, so I would assume it's not something you can use
"application's main thread works as usual." -- but if you're locking rows, any update / delete operation will get stuck, so is that working as usual?
Once the locking ends, is it ok to do all the updates right after that that were blocked?
Is your blocker thread going to do updates too?
If the application and the external device are doing updates, how to be sure they are handled in correct order / way?
I would say you need to design your application to work properly in this situation, not just try to add this kind of feature as an add-on.
The title says about releasing in another transaction, but that's not really explained in the question.
On my c# project, i have an SQL connection in MARS mode that is being used by multiple threads to perform CRUD operations. Some of these operations are required to be performed as a transaction. After i completed the data access module, i started testing and got an InvalidOperationException from one of the selects, stating that since the connection had an active transaction, the select itself needed to be in a transaction. Snooping around MSDN i found the following remark:
Caution: When your query returns a large amount of data and calls BeginTransaction, a SqlException is thrown because SQL Server does not allow parallel transactions when using MARS. To avoid this problem, always associate a transaction with the command, the connection, or both before any readers are open.
I could easily create a method that would aggregate commands into a transaction, this would even allow me to have a timer thread committing transactions on a regular interval, but is this the right way? Should i instead halt commands that don't need a transaction until an active transaction is committed?
I would stay away from MARS.
See:
used by multiple threads to perform CRUD operations
That screams "every thread one connection, and it's own transaction" unless you have a very rare case here. This absolutely does not sound like a valid use case for MARS.
I use an asynchronous process to retrieve data from a long running SQL query. The process calls a stored procedure through the SqlCommand.BeginExecuteReader() method.
At times, I would like to shut my process down and gracefully terminate any running queries.
After some testing, it seems as if calling SqlConnection.Close() is sufficient. For good measure, I also explicitly call SqlConnection.Dispose().
When running a trace through SQL Server Profiler, it appears as if the query is ended gracefully as I see a SQL:BatchStarting followed by a SQL:BatchCompleted after calling Close().
Can anyone please confirm whether closing the connection is all that is required?
Calling Close is sufficient, just a few remarks:
First of all make sure you write your Close methods inside finally block to ensure correct exception handling.
Also you do not need to call both SqlConnection.Close and SqlConnection.Dispose methods as they both do the same. Dispose method is added to implement IDisposable pattern and this method internally calls SqlConnection.Close method, which has more natural name, because we close connections, but not dispose them :)
If you are using DataReader then you have to close it as well each time after you want to use connection for other purpose.
I'll have a database object that can be accessed from multiple threads as well as from the main thread. I don't want them to access the underlying database object concurrently, so I'll write a set of thread safe public methods that can be accessed from multiple threads.
My first idea was to use a lock around my connection such as lock(oleDbConnection), but the problem is that I would have to lock it for the main thread since is one more thread that can access it. Which would mean rewriting lots of code.
But, since these threads and the main thread wont access the database very often, how about just using some of my control's (maybe the main form's) Invoke method every time I call any of the database methods from another thread. This way, as far as I understand, these methods would be never called concurrently, and I wouldn't need to worry about the main thread. I guess the only problem would be degrading performance a little bit, but as I said, the database is not accessed that often; the reason why I use threads is not so that they can access the database concurrently but so that they can perform other operations concurrently.
So does this sound like a good idea? Am I missing something? Sounds a bit too easy so I'm suspicious.
It sounds like it would work AFAIK, but it also sounds like a really bad idea.
The problem is that when writing lock you are saying "I want this code to be a critical section", whereas when writing Invoke you are saying "I want this to be executed on the UI thread". These two things are certainly not equivalent, which can lead to lots of problems. For example:
Invoke is normally used to access UI controls. What if a developer sees Invoke and nothing UI-related, and goes "gee, that's an unneeded Invoke; let's get rid of it"?
What if more than one UI thread ends up existing?
What if the database operation takes a long time (or times out)? Your UI would stop responding.
I would definitely go for the lock. You typically want the UI thread responsive when performing operations that may take time, which includes any sort of DB access; you don't know whether it's alive or not for instance.
Also, the typical way to handle connections is to create, use and dispose the connection for each request, rather than reusing the same connection. This might perhaps solve some of your concurrency problems.
Why don't you try to use Connection Pool. Every thread can do its work with a different DB connection and send the result to main thread with Invoke. Connection Pooling is a very common approach used in Servers.
See Using Connection Pooling with SQL Server