How to create a static UnitOfWork for entity framework 4? - entity-framework

Considering this class
public class XQueries
{
public IQueryable Query1()
{
using (XEntities context = new XEntities())
{
return something;
}
}
public IQueryable Query2()
{
using (XEntities context = new XEntities())
{
return somethingElse;
}
}
}
Is a connection to the database created for every (XEntities context = new XEntities()) {...} ? If so what is the correct way to create a static UnitOfWork class so that only 1 connection to exist?

You can't create a static unit of work, because by definition a unit of work is a short lived object. Because the EF ObjectContext is designed around the unit of work pattern it is a bad idea to have a single ObjectContext instance during the life time of the application. There are several reasons for this.
First of all, the ObjectContext class is not thread-safe. This means that during the unit of work of one user (in a web app for instance), another user can commit his unit of work. When they share the same ObjectContext, it means that in that situation just half of the changes are persisted and changes are not transactional. When you are lucky the ObjectContext fails and throws an exception. When you are unlucky, you corrupt the ObjectContext and safe and load crap from and to your database and find out when your application is running in production (of course, during testing and staging everything always seems to work).
Second, the ObjectContext has a caching mechanism that is designed for it to be short lived. When an entity is retrieved from the database it stays in the ObjectContext’s cache until that instance is garbage collected. When you keep that instance alive for a long period of time, entities get stale. Especially if that particular ObjectContext instance is not the only one writing to that database.

The Entity Framework opens connections only when required, for example to execute a query or to call SaveChanges, and then closes the connection when the operation is complete.
From Martin Fowler’s book Patterns of Enterprise Application Architecture in respect to Unit Of Work.
When you're pulling data in and out of
a database, it's important to keep
track of what you've changed;
otherwise, that data won't be written
back into the database. Similarly you
have to insert new objects you create
and remove any objects you delete.
You can change the database with each
change to your object model, but this
can lead to lots of very small
database calls, which ends up being
very slow. Furthermore it requires you
to have a transaction open for the
whole interaction, which is
impractical if you have a business
transaction that spans multiple
requests. The situation is even worse
if you need to keep track of the
objects you've read so you can avoid
inconsistent reads.
A Unit of Work keeps track of
everything you do during a business
transaction that can affect the
database. When you're done, it figures
out everything that needs to be done
to alter the database as a result of
your work.
Whenever I use Entity Framework for a clients (which I'd admit is rare) the ObjectContext object is the Unit Of Work implementation for the system. That is the ObjectContext will somewhat meet the three statements above. Rather than concentrating too much on the absolutely correct definition using the ObjectContext makes things a little easier for you.
Do some research on DI/IoC and Repository patterns this will give you more flexibility in handling your problem.

Related

Problem with the concept of scope in Dependency injection when using EF [duplicate]

This question already has answers here:
What is the best practice in EF Core for using parallel async calls with an Injected DbContext?
(2 answers)
Closed last year.
I have a problem with the concept of scope in dependency injection. I have registered my db context as a scope and And I save the user activity in a table using an asynchronous method without using "await".
// In Startup:
services.AddScoped<IDbContext, StorageSystemDbContext>();
services.AddScoped<IUserActivityService,UserActivityService>();
// In UserActivityService:
public async void LogUserActivityAsync(string controllerName, string actionName, ActionType actionType = ActionType.View, string data = "", string description = "")
{
await InsertAsync(new UserActivity
{
ControllerName = controllerName,
ActionName = actionName,
ActionType = actionType,
CreatedDateTime = DateTime.Now,
Description = description,
UserId = (await _workContext.CurrentUserAsync())?.Id
});
}
//In Controller:
_userActivityService.LogUserActivityAsync(CurrentControllerName, CurrentActionName,data);
I get the following error when I call same action twice immediately:
InvalidOperationException: A second operation was started on this context before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
I expected a new db context to be created with the second request, depending on the type of db context dependency registration, but according to this error, a new context was not created for the second request and used the previous one.
What is the reason for this?
I'm using Asp Net.Core MVC and EF in .Net Core 5
An injected DbContext into a service regardless of scoping will be one single reference when constructor injected. Calling multiple methods in that service will always use the same instance. AddedScoped with ASP.Net will scope the services (and DbContext) to the web request. This is the recommended scoping for a DbContext to ensure any entities loaded during a request can ensure that they are all tracked by the same DbContext instance and that DbContext should be alive for the life of that request. (i.e. to provided lazy loading support if needed) A Transient scoped dependency would mean the DbContext passed to 2 different services would be distinct references. This leads to problems where Service A calls another service to retrieve entities that it wants to associate with an entity it loaded and is trying to update. These entities are associated to a different DbContext resulting in errors or issues like duplicate data being created.
Even with a transient scope DbContext you would still have the exact same problem trying to run two calls from the same service in parallel, and there are many good reasons referenced in the comments not to use un-awaited async calls to do so. Even if your intention is to await multiple calls together, the only way to enable something like would be to internally scope the DbContext within the method call itself. This would typically involve injecting a DbContextFactory type class rather than a DbContext into the service, where the DbContextFactory is a dependency that can initialize and provide a new DbContext; Then:
using (var context = _contextFactory.Create())
{
// operations with DbContext. (context)
}
Even then you need to consider the DB synchronization guards like row and table locks / deadlocks which could rear their heads if you have a significant number of operations happening in parallel. Keep in mind with web applications the web server can be responding to a significant number of requests in parallel, each of which could be kicking off these processes at any time. (Works fine during development with 1 client, crawls/dies out in the real world.)
I found the answer here:
https://stackoverflow.com/a/44121808/4604557
If for some reason you want to run parallel database operations (and think you can avoid deadlocks, concurrency conflicts etc.), make sure each one has its own DbContext instance. Note however, that parallelization is mainly useful for CPU-bound processes, not IO-bound processes like database interaction. Maybe you can benefit from parallel independent read operations but I would certainly never execute parallel write processes. Apart from deadlocks etc. it also makes it much harder to run all operations in one transaction.

Entity Framework Memory Management and Dispose?

I'm using EF (EF Core, actually, with ASP.NET Core on OSX, but I believe this is more of a general "newbie-style" EF question, so please read on...)
I built a little logging routine that uses EF to publish log entries to my database. Sort of like this, called from a repository class:
WebLog log = new WebLog(source, path, message);
Context.WebLogs.Add(log);
Context.SaveChanges();
Where WebLog is a simple model class, Context.WebLogs is a DbSet<WebLog> collection, and Context is obviously the DbContext. I believe this is quite straightforward.
But my question is this: if I continue to add new log entries to the Context.WebLogs collection and I never do anything like reboot my server, isn't the collection just going to grow without bounds? Is there some kind of "purge" or "flush" action I can take periodically to manage memory usage (without affecting the committed rows in the database, of course--I want those to persist). Or is DbSet some sort of a special collection that won't do this?
As mentioned by DevilSuichiro above, the recommended approach is to limit the lifetime of the instances of DbContext. E.g. in a Web application you typically use a DbContext instance per request, so an unbounded number of entities added doesn't become a problem.
The closest thing to a "flush" operation is SaveChanges() that method will not try to remove references to tracked entities, as DbContext is designed to be reused after SaveChanges().
In previous versions of EF we had a Detach() API that you could use to get rid of an individual tracked reference but we don't have that API in DbContext or anywhere in EF Core.
BTW, having an instance of DbContext that is shared between multiple requests is extremely problematic because DbContext is not thread safe.

A static DbContext object for read-only purposes in ASP.NET MVC WebAPI

I'm refactoring my ASP.NET MVC 4 WebAPI project for performance optimization reasons.
Within my controller code, I'm searching for entities in a context (DbContext, EF6). There are a few thousands of such entities, new ones are added on an hourly basis (i.e. "slowly"), they are rarely deleted (and I don't care if deleted entities are still found on the context's cache!) and are never modified.
After reading the answers to this question, to this one and a few more discussions, I'm still not sure it's a bad idea to use a single static DbContext for the purpose described above - a DbContext which never updates the database.
Performance-wise, I'm not worried about the instantiation cost, but rather about the uselessness of caching requested entities if the DbContext is created for each request. I'm also using a 2nd level caching, which makes the persistence of the context even more acute.
My questions are:
1. Regardless of the specific implementation, is a "static" DbContext a valid solution in my case?
2. If so, what would be the most appropriate way of implementing such a DbContext?
3. Should I periodically "flush" the context to clear the cache in order to prevent if from growing too big?
DbContext caches entity instances when you get/query the data. It ensures different queries that return the same data map to the same entity (based on type and id). Otherwise, if you modify the same entity in different object instances, the context would not know which one has the correct data. Therefore a static DbContext would blow up over time until the process crashes.
DbContexts should be short lived. Request.Properties is a good place to save it in Web API (maps to HttpContext.Items in IIS).

Having static Repository class in a webforms project reuses entity framework connections?

I have a
public static class Repository
in my webforms project.
In the static block of that class I setup my entity framework entity object:
private static readonly ProjectEntities db;
static Repository()
{
db = new ProjectEntities("Name=ProjectEntities");
}
Then I setup some public static methods like this:
public static Order GetOrder(int orderID)
{
return db.Orders.First(o => o.OrderID == orderID);
}
The problem is that when for instance deletions fails (because of some constraint), I randomly gets some clues about that in subsequent connections, coming up as exceptions as a result of queries that should be innocent. For instance, exceptions about deletions as a result of select queries.
I never
db.AcceptAllChanges();
upon any exception, and I should not have to, because across page accesses, there should be no trace of failed queries. Or should it? Is the cleaning responsibility on me?
Those problems should not be because of me using static (please say it is not like that), so is it related to entity framework connection pooling?
Generally speaking the entity framework context is meant to be short lived - i.e. it is generally regarded as a unit of work whereby you create it for a particular task and dispose of it at the end. It's a light weight object, and should be used in this way.
You issue is as a result of the object being long lived (i.e. in a singleton shared across requests). In this case the internal state of the context is becoming invalid - i.e. you try to delete something, it cannot persist those changes to the database, and is therefore in an invalid state.
You could probably resolve your issue by calling the refresh method before making use of the object in every case - this will cause the object to update its state based on the database - but this will probably cause other issues.
However, this is the wrong thing to do - the context should be created, used and disposed per request.
Hope this helps.
I would seriously suggest you investigate the lifecycle management of your context object.
Have a look at this excellent answer as to what your options are.

What is the correct way to manage dependency injection for Entity Framework ObjectContext in ASP.NET MVC controllers?

In my MVC controllers, I'm using an IoC container (Ninject), but am not sure how to best use when it comes to the Entity Framework ObjectContext.
Currently, I'm doing something like:
using(var context = new MyObjectContext())
{
var stuff = m_repository.GetStuff(context);
}
This is the best way to manage from the point of view of keeping the database connection open for the shortest time possible.
If I were to create the ObjectContext via Ninject on a per request basis, this obviously keeps the database connection open for too long.
Also the above code would become...
var stuff = m_repository.GetStuff(m_myObjectContext);
(And when would I dispose of the context...?)
Should I be creating a factory for the ObjectContext and pass that in via DI? This would loosen the coupling, but does this really help with testability if there is no easy means of maintaining an interface for the ObjectContext (that I know of)?.
Is there a better way? Thanks
This is the best way to manage from the point of view of keeping the
database connection open for the shortest time possible.
If I were to create the ObjectContext via Ninject on a per request
basis, this obviously keeps the database connection open for too long.
Entity Framework will close the connection directly after the execution of each query (except when supplying an open connection from the outside), so your argument for doing things like this does not hold.
In the past I used to have by business logic (my command handlers to be precise) have control over the context (create, commit, and dispose it), but the downside is that you need to pass on this context to all other methods and all dependencies. When the application logic gets more complex, this results in less readable, less maintainable code.
For that reason I moved to a model where the unit of work (your MyObjectContext) is created, committed, and disposed outside the control of the business logic. This allows you to inject the unit of work into all dependencies and reuse the same unit of work for all objects. Downside is that this makes your DI configuration a bit harder. Some things your need to make sure of:
The unit of work must be created as per web request or within a certain scope.
The unit of work must be disposed at the end of the request or scope (although it is probably not a problem when the DbContext is not disposed, since the underlighing connection is closed and DbContext does not implemente a finalizer).
You need to explicitly commit the unit of work, but you can't do this at the end of the web request, since at that point you have no idea whether it is safe to commit (since you don't want to commit when your business logic threw an exception, but at the end of the request there is no way to correctly detect if this actually happened).
One tip I can give you is to model the business logic in the system around command handlers, since this allows you do define a single decorator that handles the transactional behavior (committing the unit of work and perhaps even running everything in a database transaction) at a single point. This decorator can be wrapped around each handler in the system.
I must admit that I have no idea how to register generic types and generic decorators with Ninject, but you'll probably get an answer quickly when asking here at Stackoverflow.