DataContext db = new DataContext() - as a global - c#

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

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.

many DataContext singletons to perform LINQ within a class

For a class that I have, I am noticing I basically have to use the following scenario for each function within a class. Is this inefficient? Is there a better to utilize the DataContext object?
using (var context = new SomeDataContext(getConnectionString))
{
//linq query here
}
It is designed to be used the way you mentioned. You should create a new context each and every time you do something on the database. As #Dan points out, creating a Context is extremely fast and efficient.
That's a correct and proper way to do it because it guarantees that you are disposing of the connection by putting it in a using clause. Instantiating a DBContext is not prohibitively expensive either.
With that said, you are creating one DBContext every time you query your database and disposing of it immediately, so you are not taking advantage of Caching and other niceties offered by the DbContext class.
One "cheap and dirty" way to create only one DBContext per request would be to instantiate one on Application_BeginRequest and store it in the HttpContext.Items collection (basically in a temp Cache) and disposing of it on Application_EndRequest. Each class in your project would then get the current DBContext from the HttpContext.Items cache and use it. The connection will be properly disposed since Application_EndRequest always fires regardless of errors.
A better alternative is to use a Dependency Injection framework (Structure Map, Ninject, etc.) You can google for tutorials on how to do this. SO has several questions that would help you if you are interested in implementing it.
Personal note: Don't worry about any of that stuff unless you noticee that your app is performing too slow to be acceptable. Your current approach is fine.

Exploring the pitfalls(if any) of having a DbContext for each ViewModel/Class that uses it

I am learning the Entity Framework and using it in an MVVM app where each ViewModel works with the DbContext for Data Access. Disclaimer: In a real application I know the ViewModel shouldn't interact directly with the Data Access Layer.
Given that each ViewModel is there to monitor and manipulate the state of the View by maintaining relationships with the Models themselves, I began to wonder about the implications of spinning up multiple DbContext objects, and if something like a DBContext is best left as a singleton - to which I quickly found the answer was "NO". So if the consensus is to have an instance for each use (as in the case with multiple ViewModels, or what-have-you) I still havent seen where any one mentions the potential issues with having this.
To elaborate, lets say I have two ViewModels and in each I create a Context (TestContext inherits from DbContext) to maintain the Data Access activities during the lifetime of each ViewModel:
public class MainWindowViewModel : ViewModelBase
{
private TestContext db = new TestContext();
... other code follows (properties methods etc...)...
}
public class TestViewModel: ViewModelBase
{
private TestContext db = new TestContext();
... other code follows (properties methods etc...)...
}
Are there any pitfalls with having a context in each class that can consume it?
One such thought that taunts me is if it's possible to have either context be out of sync with the other, such that one ViewModel has more recent data than the other by way of its context being more "up-to-date". Things like this I am interested in knowing.
Thanks.
EDIT
I dont hope to discover / cover every situation as that would be unique TO the situation against which one is coding. I just want to know if there are any "up-front" or obvious perils that I am unaware of being new to the subject.
Entity Framework and by extension DbContext supports the UnitOfWork design pattern. The idea being that you keep your logical "transactions" separated. Because of this, you will usually want to have each portion or feature of your application deal with its own DbContext instance.
The way you can think about it is that the DbContext holds a local copy of whatever it pulled from the database and tracks all changes made to the local data by the user. When you're ready, you tell it to push the required changes back to the database in one go.
For your question about pit-falls and perils; The Entity Framework uses what's called optimistic concurrency by default. This means that when saving the local changes back to the database, concurrency isn't checked at all. Whatever you had in your local DbContext is sent back to the database regardless of whether another user or another context in your application changed it. An excellent article explaining that and how to change the behaviour can be found here:
http://msdn.microsoft.com/en-us/library/bb738618.aspx

More efficient database access

I am new to databases and linq, so my problem may be considered trivial. I currently start all my db requests in each class with:
DataClassesDataContext db = new DataClassesDataContext()
Then I proceed to make whatever linq request I need within the method and carry on with the main application logic.
Now, two interesting queries:
1) I believe I have seen people wrapping db usage within 'using'. Such as:
using (DataClassesDataContext db = new DataClassesDataContext())
{
...
}
If this is correct, then doesn't it mean that my class can't use a member 'db' variable anymore, but rather those db requests need to be made within each function call? Also, what exactly would happen if I don't use 'using' within the calls?
2) Running my app with SQL Profiler enabled, I see lots of connections opening and closing. Does this means that each DataClassesDataContext call makes a separate connection? It seems inefficient, so is the right way to actually make the DataClassesDataContext object a static within each class being used?
In general, you should use one DataContext per database conversation. Only you can decide exactly what a conversation is, but typically it is a complete request (fetch the user's wish list, or fetch the user's closed orders, for example) that you might think of as a "unit of work."
Typically what happens is something like this:
WishList wishlist;
using(var context = new DataContext(connectionString)) {
var service = new UserWishListService(context);
wishlist = service.GetUserWishList();
}
Also, what exactly would happen if I don't use using within the calls?
The DataContext won't be disposed of properly (unless you've wrapped in a try-catch-finally, but generally you should just use using).
Does this means that each DataClassesDataContext call makes a separate connection?
Not quite. Your application will benefit from the SQL Server ADO.NET provider's built-in connection pooling. Don't worry about this, let the provider manage it for you.
It seems inefficient, so is the right way to actually make the DataClassesDataContext object a static within each class being used?
Absolutely not. DataContexts are not thread-safe (in fact, they are thread-unsafe) and this has "there be dragons" written all over it. Additionally, even a single-threaded context, a static DataContext is a bad choice because the DataContext maintains a cache (for object tracking purposes) of all the entities it has pulled from the database. Over time, the memory consumption will become ginormous.
Since you added the asp.net tag, it means you are using the context within a HTTP call. A static member context is unusable in asp.net because you need to synchronize access to it, and since your data context is required by every call, you can only serve one HTTP response at a time, a scalability fiasco of epic proportions.
This is why data context are created and disposed 'on-the-go'. In fact, the class specifications clearly calls out this use pattern:
In general, a DataContext instance is
designed to last for one "unit of
work" however your application defines
that term. A DataContext is
lightweight and is not expensive to
create. A typical LINQ to SQL
application creates DataContext
instances at method scope or as a
member of short-lived classes that
represent a logical set of related
database operations.
For ASP.Net a sensible 'unit-of-work' context is the HTTP call itself. A longer discussion on this topic can be found at Linq to SQL DataContext Lifetime Management.
The issue of connections open/close is a non-issue. Normally the connections are pooled and the 'opening' is nothing but a re-use of a connection from the pool. If you're opening is heavyweight (fully fledged login) then you're using pooling incorrectly. Comparing Logins/sec and Connection Resets/sec counters will quickly reveal if that is indeed the case.

Categories