I have a unique ObjectContext, on which I perform a SaveChanges(). This operation takes some time (~60 seconds).
This operation is executed in a thread.
My user have a "Cancel" button on the screen.
I'm able to stop the thread, but if the SaveChanges() has already started I can't find anyway to cancel it.
In fact I found no way to access the underlying transaction (I also have an Isolation level issue : this operation locks almost all tables in database, so the application cannot be used by other users).
Would it work if I closed the underlying connection ? The EF won't be able to send a Rollback instruction but I guess the database would perform it anyway, no ?
I've seen that I could use TransactionScope but it needs to access DTC and my host is not really performant when it comes to edit server/network configuration.
So if a "Entity Framework" solution exist I'd prefer that one.
is your SaveChanges() saving multiple updates? Is it possible to update then save each individually?
Then, if you are inside a transaction, and user cancels, you'd have more granularity in your saves.
Related
I'm maintaining an ASP.NET website on .NET 4.7.1 that displays some fairly extensive information using Entity Framework 6.0. Right now, all these DB queries are being performed in serial, so I'm attempting to improve performance by implementing async/await.
The problem I'm having is that running multiple simultaneous queries against the same database seems to be somewhat delicate, and I'm having trouble searching up any best practices for this type of scenario.
The site's initial implementation created a context for each of these queries inside an ambient transaction, and disposed the context after use. Upon converting the whole site to use async (and noting TransactionScopeAsyncFlowOption.Enabled), the page load began throwing exceptions claiming Distributed Transaction Coordinator needed to be configured.
System.Transactions.TransactionManagerCommunicationException: Network access for Distributed Transaction Manager (MSDTC) has been disabled.
Please enable DTC for network access in the security configuration for MSDTC using the Component Services Administrative tool.
Some searching at that point led me to believe that this could be remedied in code without perturbing configuration, so I next redesigned data layer to manage connections in a way that would allow them to share the same context. However, when testing that approach, new exceptions are thrown claiming that the connection is too busy.
System.Data.SqlClient.SqlException: Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding. The request failed to run because the batch is aborted, this can be caused by abort signal sent from client, or another request is running in the same session, which makes the session busy.
Normally this page's load time is slow (several seconds) but nowhere near the default timeout threshold.
Is async/await best suited only when the queries to run in parallel connect to different databases? If not, is MSDTC the only way to enable this behavior? Or is it perhaps just not a wise thing to blast a single database with so many simultaneous queries?
I am not able to understand exactly what changes you have done to the application. I am also not sure that the application was correctly written in the first place and it was following reasonable practices. But here are a few data points that I hope can help:
Async support in EF is designed to be used to yield threads back to the pool while waiting for I/O so that the application can process a higher number of requests using less threads and resources. It is not meant to enable parallel execution using the same DbContext. Like the majority of the types in .NET, the DbContext is not thread safe (in any version of EF) so you cannot safely execute multiple queries (async or not) in parallel on the same context instance.
Using separate DbContext instances that don't share state or connection objects should be fine, however it is recommended that in ASP.NET you still use a single thread at any point in time to process a request (when you make an async call that yields, processing may continue on a different thread, but that is not a concern) rather than trying to parallelize work within the same request.
Also, regarding the exception from System.Transaction, it may very well be that something you changed is now causing multiple connections to auto-enlist in the same System.Transactions.Transaction, which may require escalating the transaction to a distributed transaction.
I won't try to come up with a complete explanation for the timeouts, because as I said, I am not sure I understand what changes you made to the application. But it is perfectly possible that if you create too many threads, some of them will end up starving and timing out. It also extremely hard to anticipate everything that could go wrong if you start using types are not thread safe (e.g. database connections, DbContext) from multiple threads.
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 have created a windows application(using c# .net) for debugging contest in our department.
in this many user use the same database to select the list of questions and update the marks in their respective id alone.
does it required to use threading concept when they update their marks in the database..
any1 please help me..
thanks in advace...
Mutil-Threading or multiple threads are used in scenarios where you want to do more than one task at one time or do some tasks simultaneously. You should think about your scenario and possible use of multiple threads in your scenario. If you think there is some task which can be divided in to two separate tasks and they can run in parallel, you can use multi-threading to gain performance improvements. Similarly if you think there is some task that is heavy and takes huge time you can move that task to Background Thread and use main thread to deal with some other task in parallel. It all depends on your scenario.
Now coming to your scenario if it is a windows forms application most likely there will be only one user of this app at one time who will be interacting through UI. If this assumption is correct i don't think so you will need multi-threading. If user is doing some inputs thorough UI and he clicks save button at the end to save info in DB you don't need multi-threading a single UI thread will be enough to do this
No this is not needed. Each user will cosume a connection from the database connection pool, and those work concurrently and no parallel programming is required.
If you update a database from different threads, it will not corrupt. This is different from regular C#, where you need to apply locks to protect your objects. You may be required to use transactions to ensure that your database updates don't interfere with each other at a higher level. Very simply put, transactions ensure that your database stays consistent if you edit your database at multiple tables, or if your database changes depend on the database contents, such as adding an order from a customer, transactions prevent you add an order for a deleted customer.
You need to use non-UI thread for any database interactions, otherwise UI may become unresponsive. E.g. if you execute a long query from UI thread (or your connection was disrupted, or the database is under heavy use or whatever, anything that can go wrong - will go wrong), UI thread gets blocked until full response is received.
In the situations where you have multiple users, which may update the same data in the database, you may need to introduce transactions to ensure correct control and data flow - ACID.
My team and I are working on an application that accesses a "huge" database, roughly 32M rows in 8 months. The application is a RIA Domain Service application. We have optimized the application and the database design in such a way that even on a box with very limited resources the response time is never more than few seconds.
However, there are certain tasks that need to be performed on a large record set (at least 2-3M records per operation). An example is the generation of a monthly report. Definitely we cannot keep the application waiting for a result, because it would hit either the 30 seconds timeout.
After reading this post, I thought I could create an [Invoke] method, which spawns a new thread, and consequently it would free the client up. The thread would be in charge of extracting data from the DB and writing them nicely in a PDF. I've tried to implement this scenario, but I get an exception, which says that the underlying connection has already been disposed...
Is this approach correct? Can I achieve what I am trying to do or there is some issue I cannot overcome? And is there any better way to do this?
Cheers,
Gianluca.
Ok, I've realized my question is a bit silly.
As far as I understood, the ObjectContext exists as long as the client is connected, otherwise it gets disposed. Because I was writing an Invoke method that does not require any change tracking, I have resolved by:
- spawning a new thread from within the Invoke method
- instantiating a new EF context inside the worker thread
- disposing the new EF context as soon as the separate thread operation is terminated.
Cheers,
Gianluca.