Multiple Users Concurrency Issue? EF6
It's a backend API with EF6 and frontend React/js coupled together (can't run the API separately). When multiple users try to upload a file at the same time, or run the main loop to perform calculations, the app crashes. The error message from the log is:
There was also a duplicate key error, but that must stem from the concurrency issues we're seeing.
The site works as intended even if users upload and run the main loop seconds apart, just not at the same time.
Can anyone pinpoint what this error actually means and the resolution? I've spent several hours reading, and it seems like it comes down to improper db context usage, but we instantiate a db context whenever we need it. I found an article that says this (see attached). I think we're doing that, but I don't know how to confirm.
30 Replies
None of the db contexts are wrapped in a
using
statement either. There is also no direct _db.Dispose()
being called. It's all being handled by the GC, would this be any issue?
There's also endless static
methods being used nearly everywhere, that I would imagine are manipulating state as well....Old contexts not being disposed sounds like it could be it. Eventually it'd just run out of connections on the db
I've had this issue before, and it was because of Undisposed DbConnections
Always be sure to dispose of DbConnections and IDisposables that have fufilled their purpose (or use the
using
statement)
And, are you sure you are running your backend API multi-threaded? Using something like the Semaphore
class?So you think every time a _db context is being used, do it within a
using
? Right now, we're just directly instantiating at the top of the controller.
To be honest, I don't know, I wasn't sure how to confirm if it was single or multi. Not using Semaphore.
So if we're not using any out of the ordinary things, then the api is single threaded?Yes, I would say from the sounds of, it sounds like a single threaded application
Can you share an example if possible?
Ok, I'd imagine that's correct. It's really just a poorly structured EF6 Api... Hm, sure, let me share the Upload Controller, which the app was failing here when multiple users were trying to upload.
https://hastepaste.com/view/nlX1D
There is nothing wrong with single threaded applications, they are much easier to work with
Lemme check
Again, very poorly structured.
What's happening in
Context()
Can you tell me too, is the Dispose method at the bottom actually doing anything? Some other dev put it there, but that's the only implementation of it, and it's never being called, etc.
Meaning?
It's just the db context.
Oh, I see
Usually in .net core it's through DI with the service, but not in EF6 and this project was near "done" by the time i started, so didnt implement Automapper, etc
You mean, a class like this?
I am aware too that this is "fake async" methods, I am having the one dev fix that at the very least, awaiting and making all possible methods async.
Yes, correct!
Let me grab a copy.. one sec...
The dispose is not doing anything if it is not being invoked
Actually, no, I might be wrong about this
I don't think you should dispose of it
yeah since it's overrirding, i wasnt sure if it is still in fact doing something?
even though there's no direct
db.Dispose()
call.You approach is much more rudimentary than ours
Okay, yeah I've figured it
DBContext will dispose of itself fine
I was wrong about that bit
So you don't need to manually dispose, nor do you need to use using statements
Yeah, through the GC, regardless if using
using
or not.What you do need to do, is don't initialize on top of the controller
However, the timing of it could differ, and i'm not sure if that matters, when there's multiple users.
No, not even through the GC, DBContext manages it's own lifetime
What you should do, is move the initialization of
db
into the methodsOk, so having it at the top means it's being shared rather than one instance per request?
Example:
Becomes
Gotcha yea
That, and what happens is likely that that
DBContext
becomes cachedI did read about that too, and the cache becomes stale, but i couldnt really inquire further about when/how/what that all meant lol
Hopefully this solves your issue, good luck 👍
Thank you!