I have ASP.Net 4.7.2 window service which is processing NServiceBus messages. Currently it is deployed to On-Premise server. It has retry mechanism as well and working fine. Now I am going to containerizing it. While running into docker window container, it is doing SQL operation using Entity framework and giving exception as mentioned below:
The configured execution strategy 'SqlRetryingExecutionStrategy' does not support user-initiated transactions. Use the execution strategy returned by 'DbContext.Database.CreateExecutionStrategy()' to execute all the operations in the transaction as a retriable unit.
While running locally by installing manually or on On-Premise server, it is working fine but in container it is throwing exception.
Can any one help me what can be the root cause?
It sounds like the piece of code does manual transaction management and is not wrapped within an execution strategy execute.
if your code initiates a transaction using BeginTransaction() you are defining your own group of operations that need to be treated as a unit, and everything inside the transaction would need to be played back shall a failure occur.
The solution is to manually invoke the execution strategy with a delegate representing everything that needs to be executed. If a transient failure occurs, the execution strategy will invoke the delegate again.
https://learn.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency#execution-strategies-and-transactions
using var db = new SomeContext();
var strategy = db.Database.CreateExecutionStrategy();
strategy.Execute(
() =>
{
using var context = new SomeContext();
using var transaction = context.Database.BeginTransaction();
context.SaveChanges();
transaction.Commit();
});
``
Related
Background:
I have a web application in which I have SignalR as well.
I'm using AutoFac as DI container where my database is registered as
builder.RegisterType<MyDbContext>().AsSelf().InstancePerLifetimeScope();
i.e. MyDbContext is registered as PerRequestDependency.
The ChatHub is also registered with same dependency level. i.e.
builder.Register<IHubContext>((c) =>
{
return GlobalHost.ConnectionManager.GetHubContext<ChatHub>();
})
.InstancePerLifetimeScope();
Problem:
The problem I am facing is - The DbContext throws error saying there are multiple threads calling the DbContext.
Here is the exact error:
System.NotSupportedException: A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe. at System.Data.Entity.Internal.ThrowingMonitor.EnsureNotEntered()
Note: I have looked into entire code and I am 100% sure that I have awaited all async calls to the database.
Possible Solution:
If I change the AutoFac registration to per below then the error goes away but I feel, it will require more database connections.
builder.RegisterType<MyDbContext>().AsSelf();
i.e. remove InstancePerLifetimeScope
Expectation:
Better solution than increasing database connections.
Make sure you don't open the same entity twice.
Example:
var x = db.user.FirstOrDefault(a=>a.id == 1);
.
some code here
.
var y = db.user.FirstOrDefault(a=>a.id == 1);
y.userName = "";
All,
I am using Change Feed Processor Library.Want to know the best way to handle service failure along with the exceptions/errors scenario's in ProcessChangesAsync method. Below are the events am referring to.
1) Service failure - Service having the processor library crashed in the middle of some operation. How to start the process from the same document(doc on failure instance)? is there any inbuilt mechanism where change feed will start with the last failed documents? E.g. Let assume,in current batch we have 10 docs.5 processed successfully and then service breaks because of network failure or by some other reasons.Will my process starts with 6th document once service is re-started? How to achieve this?
2) Exception and Errors- Any errors in ProcessChangesAsync method can be handle using try catch at the global level but how to persist those failure records and make them available for the next batch? Again,looking for any available inbuilt mechanism in change feed process.
1) The Processor Library, by default, checkpoints after a successful run of ProcessChangesAsync. In the latest library version, you can customize the Checkpointer to do manual checkpoints in case you need it. If for some reason the processor shuts down before checkpointing, then it will start processing next from the the last successful checkpoint stored in the Leases collection. In your case, it will start with the first document again, so you will never lose a change but you could experience double processing (this is an "at least once" model).
2) There is no built-in mechanism that you can leverage, handling exceptions within the ProcessChangesAsync is your responsibility. You could not only add a global try/catch but, in the case you are looping over the documents, add a try/catch inside the loop, to handle a failing document (maybe send it to queue for later analysis/post-process) without losing the batch. If you require logging for those errors (I'm assuming that's what you mean by persisting errors?), then the latest version is compatible with LibLog, so plugging your own custom logging is as simple as:
using Microsoft.Azure.Documents.ChangeFeedProcessor.Logging;
var hostName = "SampleHost";
var tracelogProvider = new TraceLogProvider(); //You can use any provider supported by LibLog
using (tracelogProvider.OpenNestedContext(hostName))
{
LogProvider.SetCurrentLogProvider(tracelogProvider);
// After this, create IChangeFeedProcessor instance and start/stop it.
}
Source
Extra info for the comments
To avoid exceptions halting the batch or causing a batch to be reprocessed, you can have handling like this:
public async Task ProcessChangesAsync(IChangeFeedObserverContext context, IReadOnlyList<Document> documents, CancellationToken cancellationToken)
{
try
{
foreach(var document in documents)
{
try
{
// Do your work for the document
}
catch(Exception ex)
{
// Something happened with the current document, handle it, send it to a queue / another storage to analyze, log it. This catch will make the loop continue with the next.
}
}
}
catch(Exception ex)
{
// Something unhandled happened, log it and avoid throwing it again so the next batch is processed
}
}
We are using the SQLite.NET PCL in a Xamarin application.
When putting the database under pressure by doing inserts into multiple tables we are seeing BUSY exceptions being thrown.
Can anyone explain what the difference is between BUSY and LOCKED? And what causes the database to be BUSY?
Our code uses a single connection to the database created using the following code:
var connectionString = new SQLiteConnectionString(GetDefaultConnectionString(),
_databaseConfiguration.StoreTimeAsTicks);
var connectionWithLock = new SQLiteConnectionWithLock(new SQLitePlatformAndroid(), connectionString);
return new SQLiteAsyncConnection (() => { return connectionWithLock; });
So our problem turned out to be that although we had ensured within the class we'd written that it only created a single connection to the database we hadn't ensured that this class was a singleton, therefore we were still creating multiple connections to the database. Once we ensured it was a singleton then the busy errors stopped
What I've take from this is:
Locked means you have multiple threads trying to access the database, the code is inherently not thread safe.
Busy means you have a thread waiting on another thread to complete, your code is thread safe but you are seeing contention in using the database.
...current operation cannot proceed because the required resources are locked...
I am assuming that you are using async-style inserts and are on different threads and thus an insert is timing out waiting for the lock of a different insert to complete. You can use synchronous inserts to avoid this condition. I personally avoid this, when needed, by creating a FIFO queue and consuming that queue synchronously on a dedicated thread. You could also handle the condition by retrying your transaction X number of times before letting the Exception ripple up.
SQLiteBusyException is a special exception that is thrown whenever SQLite returns SQLITE_BUSY or SQLITE_IOERR_BLOCKED error code. These codes mean that the current operation cannot proceed because the required resources are locked.
When a timeout is set via SQLiteConnection.setBusyTimeout(long), SQLite will attempt to get the lock during the specified timeout before returning this error.
Ref: http://www.sqlite.org/lockingv3.html
Ref: http://sqlite.org/capi3ref.html#sqlite3_busy_timeout
I have applied the following solution which works in my case(mobile app).
Use sqlitepclraw.bundle_green nugget package with SqlitePCL.
Try to use the single connection throughout the app.
After creating the SQLiteConnection.
Apply busytime out using following call.
var connection = new SQLiteConnection(databasePath: path);
SQLite3.BusyTimeout(connection.Handle, 5000); // 5000 millisecond.
I have WebService that is hosted by ASP.NET web site. Inside the TransactionScope object is used to handle transactions:
using (TransactionScope scope = new TransactionScope())
{
...
scope.Complete();
}
The problem is that during debugging, when I am going through each line in step-by-step mode,
transaction timeout is occurred and any attempt to access DB crashed with '' error, and as a result: further debugging is prohibited.
How could I handle that without deleting mentioned lines of code?
P.S. I've tried to find, how to increase a time-out of created transaction, but didn't find something helpful.
Any thoughts are welcome.
Thanks.
You can specify an infinite timeout for the Transaction by passing in a zero length TimeSpan as part of the constructor:
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(0)))
The TransactionScopeOption of Required is what is used as default with your parameterless constructor.
See http://msdn.microsoft.com/en-us/library/ms172152(VS.90).aspx for more information.
After nearly 5 months with this configuration I am now getting a series of:
"A process serving application pool 'Classic .NET AppPool' suffered a fatal communication error with the Windows Process Activation Service. The process id was '1640'."
This leads to:
Application pool 'Classic .NET AppPool' is being automatically disabled due to a series of failures in the process(es) serving that application pool.
I cannot, for the life of me, figure out what changed to start causing this nor can I figure out how to possibly dig in deeper to find out what is causing it to fail.
I recently (2 weeks ago) started adding Entity Frameworks to my solution. Right before this happened I did get an "out of stack space" error due to a reported self-referenced call. I cannot find any calls like that in the code I wrote and am suspecting EF may have added a join in my simple (3 table) model that is wrong.
Any ideas on where to start looking? What would cause the AppPool to fail?
TIA
NOTE:
An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll
I have an outside object that calls this method to get a single record:
public static AutoNegotiationDetails GetAutoNegotiationByCompany(Guid companyId)
{
return RivWorks.Controller.Negotiation.GetAutoNegotiationByCompany(companyId);
}
That method calls into:
internal static AutoNegotiationDetails GetAutoNegotiationByCompany(Guid companyId)
{
var autoNeg = from a in _dbRiv.AutoNegotiationDetails where a.CompanyId == companyId select a;
var ret = autoNeg.FirstOrDefault();
return ret;
}
In stepping through it I can set a break point inside the first method, step into the second method, see the record populated, return to the first method then finally exit the method. At that point my IDE locks up for a few seconds until I get the StackOverflow error.
For a more accurate picture of the whole system:
Running WebOrb30 on the IIS machine.
In the VS IDE -> Attach to Process (INETINFO.exe)
Log into WebOrb30 -> Management Console -> Drill down to service entry point -> Enter CompanyID into input box -> Click Invoke
Hit break point in VS IDE -> (See above)
NOTE:
Looks like it may be caused by another issue in EF. See C# - Entity Framework - An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll for further clarification.
I may be that you have two apps/sites using one app pool, but the apps/sites are running different .net versions.
This might not be the case, but its the only similar recurring problem i've ever had with iis.
Because of a bug in my Entity Framework I was getting a cyclic call into one of my relationships. This was causing a stack overflow which was reported to WebOrb as a general error and WebOrb would halt causing the App Pool to crash. (I still don't quite understand all the specifics). When I rebuilt my EF Model without the relationships the behavior went away. (sigh/)
EF will be another question (or series of questions).