Managing Database Connections in ASP.Net MVC - c#

I am new to ASP.Net MVC and I have written a number of Controller classes that have this ivar:
private ApplicationDbContext db = new ApplicationDbContext();
I have also read that each request creates a new instance of the Controller.
I am concerned about database connection churn.
Should I be using a single global connection object instead? Or is there connection pooling happening behind the scenes and I shouldn't worry about it?

For Entity Framework ORM tool, it is not recommended to use DbContext as a singleton instance, so, avoid to keep it on the global.asax. A good pratice is to use it with the pattern Unit of Work. Read this article.
In this another article you can see sample pros and cons about how to keep an instance of DbContext.

Related

Entity Framework Core and multithreading

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.

Use the same DbContext in the entire controller, or use a new DbContext whenever need it?

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.

DataContext db = new DataContext() - as a global

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

Should I be opening a database connection in my controllers?

My controllers need to get data that is passed back to the view. Where should I open a connection to pass to the repository? Here is an example. This is a part of one of my controllers.
using (var connection = this.GetActiveConnection())
{
var repository = new RefRepository(connection);
var codes = repository.GetPoACodes();
}
Is it bad practice to be opening a connection in the controller? If I don't pass it via the controller, where should I pass the connection to the repository?
Actually Repositories must handle connection themselves, it shouldn't be controller concern.
Controller class must remain thin, and if it gets fat, it would be a code smell.
It would a very good practice if you can use a Dependency Injection Framework (like Ninject, StructureMap, ...) to wire those dependencies , to handle DbContext or Session and SessionFactory (EF or NHibernate), Transaction or namely Unit of Work pattern, Exception Handling and Logging if you want to go thus far.
If you're using Visual Studio then in Project Templates there is an option which create repositories also, you can create a sample project, read the code, and learn how the code is organized.
In this article, under Web API header, you can find out how to do it.
No, you should not open a database connection on your controller.
Controller should talk to your "domain model", which is not the same as your database schema.
In your case, maybe your repository must handle it.
Or even more, if your using Entity Framework or NHibernate, for example, it'd be better let them handle that matter.

Managing EntityConnection lifetime

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.

Categories