Open michaelcsikos opened 4 years ago
DbContextManager
relies on the CSLA LocalContext
to get isolation.
LocalContext
defaults to using AsyncLocal
to achieve that isolation. This is a change from earlier versions of CSLA where thread local storage (TLS) was used.
In CSLA 5.1 you can configure your app to use the old TLS behavior because I added /ApplicationContextManagerTls as a type in Csla.Core
.
You can just copy-paste that code into your project though, and use it in 4.11 too.
Just configure ApplicationContext.ContextManager
(?) on app startup.
That said, I don't know why AsyncLocal
wouldn't work - it is supposed to maintain per-thread and per-context state.
And maybe that last bit is the problem? Maybe because the code is all running on the client, it is carrying the UI context through every thread, and so they are all treated as being part of a single context? Hmm...
If that's true, then I should change the Windows Forms default behavior back to using TLS.
Thanks for your replies, Rocky. I've tried with the ApplicationContextManagerTls
and now it's throwing, "Cannot access a disposed object." I noticed in another solution I've used Csla.Windows.ApplicationContextManager
but that gives me the original "A second operation" exception.
I'll try to make a bare-bones sample that reproduces this. Maybe I'm doing something silly, or there's something funny with EF Core 3.1.2.
It is also the case that if you are using CSLA 5.1 you can avoid the use of the CSLA db context manager types, and instead switch to dependency injection of the EF context directly.
Question In a new application I'm getting the following exception:
A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of 'DbContext', however instance members are not guaranteed to be thread safe. This could also be caused by a nested query being evaluated on the client, if this is the case rewrite the query avoiding nested invocations.
For years, I have fired off
async
fetch requests in different parts of the UI simultaneously, and this has never been an issue. In my old apps, I can't reproduce it, but in the new app it happens every time.To test it, inside the
using (var ctx = DbContextManager<EfDbContext>.GetManager())
I compare theDbContext
to see if the new one is the same instance as another one that's already been created. I'm firing off a fewasync
requests at once, e.g.In the new app, the
DbContext
is sometimes being shared, and the exception is thrown. I thought theDbContextManager
should only share theDbContext
"vertically", i.e. within a save operation, the children use the same context as the parent, not "horizontally", where different threads are fetching data.The exe and WindowsForms assemblies are full .NET; the Business, Dal, DalEf assemblies are NetStandard 2.0 with EF Core. The old app is .NET 4.7.2 with EF Core 2.2.6; the new app is .NET 4.8 with EF 3.1.2.
I've tried rolling back versions of EF NuGet packages to match the older projects, but it's still happening. I'm stumped.
Version and Platform CSLA version: 4.11.2 Platform: WinForms