DbContextScope Pattern for EF Core 3 - entity-framework

Some of you may be familiar with the DbContextScope library, which allows you to nest scopes within your code, and allow those scopes to share a common DbContext. The idea is that the DbContext gets managed for you by the scope library, and instead of calling SaveChanges() on the context, you call SaveChanges() on the scope. The magic happens because the scope will only save all the changes on the context at it's outer-most call of SaveChanges(), so all the nested operations performed on the DbContext get saved in a single transaction at the outer scope-level.
Now that DI is a first-class citizen in .NET Core, it appears that scopes have also become an important part of the .NET Core ecosystem, and the EF Core team, knowing this, has implemented scoping based on allowing DbContexts being injected by the DI system, and (I assume) allowing change saving to happen at scope-levels and not directly on the DbContexts in some way.
So my question are these:
What is the appropriate way to share a DbContext via a scope, allowing the SaveChanges() be managed at the scope level and not the code-level that typically calls SaveChanges() on the DbContext?
Are there new mechanisms in EF Core that manage this for you, just like DbContextScope did this for you as a 3rd party library?
Save me the drama, and spare me the lectures on why you think UOW needs to be implemented in addition to EF. K thnxs bye.
UPDATE: As of 6/2020 there are several forks of DbContextScope that work with EF Core 3.
UPDATE: Forks of this project can be viewed here: https://github.com/mehdime/DbContextScope/network
There are several EF Core 3 versions... I haven't tried any yet, but there you go.

Since Entity Framework 5.0.0, there is IDbContextFactory<TDbContext> that lets you control the creation and disposal (!!) of your DbContexts.
Instead of registering your DbContext with AddDbContext or AddDbContextPool, you can now use AddDbContextFactory or AddPooledDbContextFactory, respectively.
Note that this feature takes care of one of the problems that DbContextScope solves, not all of them. As for what the other problems and solutions are, refer to Mehdi's original post. It is long but excellent.

DbContext sharing is built-in to the Dependency Injection design for EF.
The DI container will generate a scoped DbContext instance for each web request. You can share the DbContext instance from any component that has a dependency on it, and call SaveChanges(), or manage transactions in your outer controller.

Related

How to use Autofac to inject the same instance of DbContext for processing an HTTP request without causing concurrency issues?

I'm working on an ASP.net Web API application with Autofac and Entity Framework.
I've been breaking apart different my service classes into smaller classes in order to make my code more testable and to make my code more SOLID.
I'm using Autofac to inject Entity Framework DbContext into my various helper classes. This becomes problematic because if I use entities queried from DbContext in two different helper classes, I get an error when Entity Framework tries to produce a query.
The error says that Entity Framework cannot produce a query with entities from two different instances of DbContext.
Clearly, the solution is that I need to configure Autofac so that the same instance of DbContext is injected into each of the helper classes, but I'm afraid that if I try to do this, I may get concurrency issues when this application gets deployed to a production environment and many people use it at once.
How do I configure Autofac so that when a request hits my application, my API helper classes all get the same instance of DbContext, but I don't have concurrency issues across multiple requests?
An alternative to the action filter recommended by the Autofac documentation (https://autofaccn.readthedocs.io/en/latest/faq/per-request-scope.html#no-per-request-filter-dependencies-in-web-api) see: "No Per-Request Filter Dependencies in Web API" and manually going to the DependencyResolver for others:
You could have a look at the Medhime DbContextScope unit of work provider. (https://www.nuget.org/packages/EntityFramework.DbContextScope/) compiled for both EF6 and EF Core.
The injected dependencies for your classes becomes a DbContextScopeFactory for the top level, and an AmbientDbContextLocator for your services. These don't "break" with Web API's limitation on the request lifetime scope. The ContextScopeFactory would be initialized once and supply the DbContext, while the locators will be fed that single instance.
It may be worth having a look at if managing context references across services and an API action prove clunky.

How to implement DbContext hierarchy

What I'd LIKE to do is manipulate EF to support plugins that access a shared database. So the database would contain all of the tables for the main application plus all of the tables required for each plugin. As the application doesn't know anything about the plugin data structures, it cannot be responsible for their management. The plugins are solely responsible, and create the tables themselves. However, the plugins know about the host application and its data structures, so ideally should be able to reference them and even inherit from them, resulting in a database that is extensible yet able to implement optimized patterns.
In EF, this translates to a HostContext that contains the DbSets appropriate for the Host. Each Plugin, I thought, should have a PluginContext that inherits from HostContext that contains the DbSets needed by the plugin. The entity classes included in PluginContext would then be able to reference HostContext entities, and/or inherit from those entities, and EF would be able to resolve the table mapping and relationships.
I'm using EF6. When I attempt the above and try to list the single entity I've included in the PluginContext, an exception is thrown complaining that the entity doesn't exist. Sure enough, no matching table has been created.
Is what I'm attempting to do supported by EF? If so, what am I doing wrong?
As I mentioned here: EF6 Empty Model target string
I began this effort using Rowan Miller's example here: http://romiller.com/2013/02/15/extending-and-customizing-code-first-models-part-2-of-2/
In the end, I abandoned that approach, for a few reasons: 1) I couldn't get it to work (I can't remember exactly why but I do suspect it was related to differences in EF since the article was written), and 2) I didn't like the need to write manual migrations.
I ended up with PluginContexts that inherit from HostContext, as I had hoped, and am able to reference and even inherit from host entities. This has restrictions in its use though:
My plugin logic is completely self contained. I have no need for the host application to manipulate or create plugin entities. Therefore, I am not trying to get the system to subsitute any plugin entities for host entities. If construction of a particular entity subclass is required, then a plugin method must be provided for that and an inheritence hiearchy will be utilized.
Migrations can be built even on the plugin context as per normal. However, that migration may easily include migration code from the Host Context. So I have to remember to look for and remove these instructions. This is typically very straightforward and I believe is much less effort than building the equivalent from scratch.
If there is any change to the Host Context then this must be reflected in every Plugin Context. Basically, this means anytime a new migration is created to reflect changes in Host Context, migrations must be created for each plugin as well, even though that migration may be empty (it isn't really - the critical part here is updating the Model in the latest MigrationHistory record to reflect the Plugin model that has been changed because of the inherited Host model).
This approach is being used to extend an in-house application with in-house plugins, and so may not be as easy to adopt in other scenarios which Rowan's solution is probably better suited.

Using DbContext and Database First in EF 4.1

I have started working on a new project and am switching from LinqToSQL to EF 4.1 as my ORM.
I already have a database set up to work with and so am going with the database first approach. By default the EF generates a context which extends ObjectContext. I wanted to know if a good approach would be to replace it with DbContext.
Most of the available examples deal with only Code First and DbContextbut DBContext can be used with Database First too. Are there any advantages I get by using the DBContext? From what I have read the DBContext is a simplified version of the ObjectContext and makes it easier to work with. Are there any other advantages or disadvantages?
You will not replace anything manually. You will need DbContext T4 Generator available at VS Gallery. Don't touch your autogenerated files - your changes will be lost every time you modify EDMX file.
I answered similar question last year. Now my answer is mostly - for new users DbContext API is probably better. DbContext API is simplified - both in terms of usage and features but you can still get ObjectContext from DbContext and use features available only in ObjectContext API. On the other hand DbContext API has some additional performance impact and additional layer of bugs. In simple project you will probably not find any disadvantage in DbContext API - you will not see performance impact, you will not use corner features available only in ObjectContext and you will not be affected by occasional bugs.
A lot of information and blog posts was collected since DbContext API was released so you don't have to be afraid that you will not find description of the API. Also ADO.NET team now uses DbContext API as their flag ship.
I'm not a big fan of DbContext API but my opinion is not related to its functionality but to its existence - there is no need to have two APIs and split development capacity of ADO.NET team to maintain and fix two APIs doing the same. It only means that there is less capacity for implementation of really new features.
I'm using it now with Oracle on an add on to an existing application. The simplification that Ladislav refers to works well for me on this project as I am short on time and resources. I have not found any gotchas as long as you stick to simple CRUD operations and less than ~150 tables.
You can still use metadata annotations to provide basic validation and localization and there is enough documentation out there but you won't find much on official Microsoft sites.

Access DbContext from IQueryable

I am trying to implement a caching pattern which may need to utilise Redis. The problem with this pattern is that I need to disable Configuration.ProxyCreationEnabled and then re-enable it afterwards to avoid any issues across a web farm.
What I would like to do is access the DbContext from the IQueryable so I can do this once instead of everywhere. The easiest way to do this is to pass the DbContext being used into my caching extension, however I came across this post:
Access DataContext behind IQueryable
Is there a way of accessing the DbContext in a similar manner to the link above using EF 4.1 Code Fist (DbSet's, etc)?
I have tried to find this myself but have struggled to find the base class from the referenced DbSet in the IQueryable using reflection.
The solution mentioned in Access DataContext behind IQueryable is a hack and should not be used. It relies on the name of a private member variable in the class implementing IQueryable. This means that the implementing class could change in a future release of EF/.NET Framework and break your code. Since the DbContext is not accessible through the IQueryable interface, you should pass it into your caching extension to avoid making assumptions about the IQueryable implementation. Doing so will also more clearly establish the dependency on the DbContext in your caching interface, instead of burying it in the implementation.

EF4: ObjectContext Lifetime?

I am developing a WPF desktop app that uses Entity Framework 4 and SQL Compact 4. I have seen two distinct styles of Repository classes:
The Repository instantiates an ObjectContext, which is disposed of when the Repository is garbage-collected. The lifetime of the ObjectContext is the same as the lifetime of the application.
A separate DataStoreManager class creates and holds an ObjectContext for the life of the application. When a repository is needed, a command gets an ObjectContext reference from the DataStoreManager and passes it to the constructor for the New Repository. The lifetime of the ObjectContext is the lifetime of the application.
Is either approach considered a bad practice? Does either present any absolute advantages over the other? Is either approach considered best practice? Is either more widely accepted or used by developers than the other? Thanks for your help.
I would have thought that holding an ObjectContext open over multiple accesses would be bad practice. As soon as it becomes corrupted then you would need to recycle in and handle the corruption.
The Repository pattern is more for abstraction of data access but doesn't necessarily map to lifetime of context.
The unit of work pattern is more about encapsulation of one or more database/repository accesses i.e. a use case may have you adding a new Blog and then adding the first default post, this may require calling two repositories, at this point you might want to share the context and encapsulate these two commands in a transaction. Adding a second post might be done hours later and be a new context/unit of work.
DJ is right in mentioning Context lifetimes which you'd set generally at an application level.
The best practice is depended on how your users are going to use the application:
And how your application is structured.
if there is only one user using your application at one time, you can even create your entity context as a static instance.
context can be used per request, per thread, per form.
read more: http://blogs.microsoft.co.il/blogs/gilf/archive/2010/02/07/entity-framework-context-lifetime-best-practices.aspx