In my ASP.NET Core application, I have some complex business logic involving multiple threads doing database operations outside the scope of an HTTP request. Accessing the database from the same thread processing the request is trivial, but when spawning threads that requires their own DbContext, this turns out to be tedious. As the DbContext itself is not thread-safe, I have tried to create a new DbContext together with its options in addition to obtaining a DbContext from an IServiceProvider. With both approaches, I get the following exception:
An attempt was made to use the context while it is being configured. A
DbContext instance cannot be used inside OnConfiguring since it is
still being configured at this point.
I'm getting the impression that I'm approaching this problem the wrong way and that I'm not supposed to handle database connections like this. How am I then supposed to obtain a DbContext in a separate thread from the one processing incoming requests?
I tested and it works:
var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
optionsBuilder.UseSqlServer(DbConnectionString);
using (var context = new ApplicationDbContext(optionsBuilder.Options))
{
//save or update() on *context* here
}
It turned out my test code had a small typo making it use the same DbContext across all threads. It is however required that I create a new DbContext instance but I cannot obtain one through the IServiceProvider as mentioned in my question.
Related
Is it possible to do Add, AddAsync, Update etc in .NET Core without the entity being tracked afterwards without having to write code to specifically detach the context from tracking the entity?
// select, its possible to do no trackiing
var audit = _dbContext.Audit.First().AsNoTracking();
// doing an add or update, audit is now tracked unless it's detached
_dbContext.Audit.Add(audit);
int rows = _dbContext.SaveChanges();
_dbContext.Entry(audit).State = EntityState.Detached;
I ask this because I have a windows service that consumes RabbitMq messages and writes to the database. RabbitMq receives messages via an event handler. So the database essentially becomes a singleton even though its added as transient. I could create a new db context each time. but it seems overkill. Or is there a better way?
You shouldn't have singleton DbContext because it is not thread safe.
You can take a look at this blog post for different approaches of managing DbContext:
https://mehdi.me/ambient-dbcontext-in-ef6/
I have a windows application, where I am implementing Dependency injection by Autofac. I have a DBContext class which interacts to db for sql operation. I am using EntityFramework. I have scenario that i need to fetch entities separately with data from db based on some primary key from different tables. Then after some business logic again I need to update those entities in db. But here either all fetched db entities should be updated or none. so I am following unit of work pattern for that. But when fetching db entities from repository with using same dbContext instance, it lost other entities from dbContext. I was using AsImplementedInterfaces() (from autofac) to resolve my DbContext instance, which is not working in my scenario. I changed it SingleInstance() then I am able to achieve my requirement. My doubt here, Is SingleInstance() is thread safe for windows application or for above scenario kind of work?
builder.Register(c => new PortalDbContext(connectionString)).As<IPortalDbContext>().AsImplementedInterfaces();
TO
builder.Register(c => new PortalDbContext(connectionString)).As<IPortalDbContext>().SingleInstance();
I have three repository classes, and one business layer (BL), BL calls all repository class one by one to fetch data with same DBContext instance. Then finally it calls one method DBContext.SaveChanges() which should save all entities data in once or no data should be updated if any one failed. It is working with SingleInstance() scope. But not sure if SingleInstance is thread safe or not.
According to autfac the service resolution are thread safe documentation:
All container operations are safe for use between multiple threads.
The only thing to keep in mind is that resolution context objects are single-threaded so you need to avoid component registration as:
builder.Register(c => new MyComponent(c)); //DON'T DO!
but as:
builder.Register(c =>
{
IContext threadSpecificContext = c.Resolve<IComponentContext>(); // access real context.
return new MyComponent(threadSpecificContext);
}
(see that the threadSpecificContext has been resolved, and the "c" context has not been used)
In your case you didn't make use of the "c" context at all, also see this answer.
I'm using MVC .Net. Usually I always use something like below to create one instance whenever I need to query the DB:
using (EntitiesContext ctx = new EntitiesContext())
{
....
}
Then I see lots of sample codes that always have one instance of DBContext in the controller, use it whenever needed, and Dispose it when the controller is Disposed.
My question is: which one is the right way to use it? Any advantage/disadvantage? Maybe, is there any performance difference?
Thanks
Using a context by controller instance has multiple advantages :
It's scoped to the controller, therefore if you need it multiple times you allocate only one instance
EntityFramework use local caching, then if you query multiple times over the same DbSet with the same parameters, it will match those entities in cache instead of querying the database
If you use the repository pattern, it's a good practice to share your context accross repositories. That way, each repository is able to see what as been done by other repositories if you manipulate multiple repository in the same controller scope
From the Getting Started with ASP.NET 5 and Entity Framework 6 , you can read :
Context should be resolved once per scope to ensure performance and ensure reliable operation of Entity Framework.
See a related SO post that deeply explain why it's better to use this approach.
In my MVC 5 app with EF6 started using interfaces and Ninject and ran into problems.
I call multiple implementations to get a data and when saving it entities are disconnected and have problems with many to many and similar.
So I want to make my DataContext db = new DataContext(); global so I just refer to it, not create new instance in every class.
Where do I declare it and how to call it?
DO NOT DO THAT.
At least because, due to caching, you will finish to have all the database in memory.
Your DbContext MUST have a scope as small as possible. Certainly not an application scope.
"Let the connection pool do his job".
All u need is repository pattern and Unit of work.
there is useful link about implementation
http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
There have been many question on managing EntityContext lifetime,
e.g. Instantiating a context in LINQ to Entities
I've come to the conclusion that the entity context should be considered a unit-of-work and therefore not reused. Great.
But while doing some research for speeding up my database access, I ran into this blog post...
Improving Entity Framework Performance
The post argues that EFs poor performance compared to other frameworks is often due to the EntityConnection object being created each time a new EntityContext object is needed.
To test this I manually created a static EntityConnection in Global.asax.cs Application_Start().
I then converted all my context using statements to
using( MyObjContext currContext = new MyObjeContext(globalStaticEFConnection)
{
....
}
This seems to have sped things up a bit without any errors so far as far as I can tell.
But is this safe?
Does using a applicationwide static EntityConnection introduce race conditions?
Best regards,
Kervin
EntityConnection is documented to be not thread-safe. I think you could pool them, but you cannot use a single, static connection for a Web application, as there will be many threads involved.
If your EF context is Application-wide, consider that user A has made changes (not committed) & user B has committed his changes, all changes will get committed to the database since both user A & B use the same instance
In my project, I did a per WebRequest intance of the EF context - ie. a context object is static from start through end of a web request & all operations in that request work with the same EF context. This has significantly speeded up my processing without the problem mentioned above.
One way to implement this is to use a DI container (I am using Unity) to manage the lifetime of the EF context. The per web request lifetime manager is not given out of the box in Unity, but there are tons of articles out there which show how this can be done.
HTH.