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

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.

Related

DbContextScope Pattern for EF Core 3

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.

Dependency Injection, EF Core + web api 2 architecture

My layout
project.web (.net core 2.1 web api)
Some binding models (for post/put requests) and resource models for GET requests
Controllers.
I only call interfaces from (x.api) which are resolved to x.core services.
No validation or anything. This happens inside the core layer
I've setup a few things like automapper and swagger, that are not relevant for my question.
project.api (class lib)
only contains interfaces for .core and .store projects (services, repositories and domain models)
project.core (class lib)
two kinds of services
1) Services which call the repository services (interfaces). But validate the data before calling the repo service.
2) Services that will have to execute long term stuff (IE: scanning folders, handling file information, ...). I actually created HostedServices for these as a folder could easily contain thousands of files.
project.store (class lib)
Wrapper services for my storage (Only contains helper methods so I don't have to write the same queries a hundred times.)
Problem / question
At this time I have registered all of my services and repositories as singletons in public void ConfigureServices(IServiceCollection services)
because I was using a different storage (nosql, litedb) before refactoring code to EF (sqllite)
Now the problem is that I want to register my DbContext as scoped (by default)
But my repositories (singleton) depend on dbcontext. Which means I will have to make these scoped as well. I'm ok with this, as these are only wrapper services, so I don't have to write the same queries all the time.
But some other services, that will need access to my data are singletons, and I cannot register these as scoped. Contains some data that needs to be the same for every request, and some collections and long running jobs.
I can think of two solutions
The first solution is to make a dependency to IServiceScopeFactory in my repository and use something like using (var scope = ServiceScopeFactory.CreateScope()) { scope.ServiceProvider.GetService(typeof(MyDbContext))... }
this way I can remove the dependency from my repository wrapper, but this doesn't sound clean to me.
The other solution is to register all of my services that only handle database stuff as scoped. (IE customerSservice in core only does validations and calls customerRepository) I remove dependencies from my remaining singleton services.
In those singletons, instead of depending on the customersService, I could use a rest call with restsharp or something similar
Just like how I would consume them from my windows client applications and web client apps.
I don't actually like either. But perheps someone can give me some advice or thoughts?
Well, the two options you laid out are in fact your only two options. The first is the service locator antipattern, which as the name implies, is something you should avoid. However, when you are dealing with singleton-scoped objects needing access to objects in other scopes, there is no other way.
The only other option is to reduce the scope of your services from singletons, such that you can then inject the context directly. Not everything necessarily needs to be a singleton. Generally, if you need to utilize something like DbContext, there's a strong argument to be made that your object should not be singleton-scope in the first place. If you need it to be singleton-scoped, that's most likely an indication that the class is either doing too much or is otherwise brittle.

Is it better to use POCO objects or detached EntityFramework object to expose database via WCF?

I created a WCF service in charge of exposing my database's data since I don't want the database to be directly accessed by my application (for security reasons) and i need to be able to share data with third-party applications.
My solution is structured this way: WPF application -> WCFService library -> DataAccessLayer library. (Arrows define assembly dependencies 'depends on')
To implement the WCF service I considered to simply return detached EntityFramework objects from the service BUT it forces the main application to have a dependency on the DataAccessLayer library.
The only way i can get around that is generating POCO objects and use them to send them over the wire, but now i have to map values back and forth EntityFramework.
At the moment i'm generating POCOs dynamically via a T4 template and I'm using AutoMapper to map values back and forth EntityFramework.
The Wcf service will just have to implement the repository pattern to expose data.
Is this a good solution? Are there any other option?
Is there any shortcoming i should be aware of?
Depending on your constraints, I would have to agree with this solution.
I created an almost identical solution, although our motivations were slightly different. Our client was Delphi Win32, and at the time didn't have good support for JSON, so we had to use SOAP.
The client also didn't support nullable primitives, so the POCOs removed all unsupported types, and performed other changes to ensure interoperability, then we used Automapper custom mappings to handle the two way conversions.
All the WCF services (contracts and implementations) where also generated by T4 templates, using a generic repository. With T4 templates, I was able to generate a separate WCF service per table for CRUD operations, and then manually created WCF services that were business specific.
Finally, I was also able to used T4 templates to generate the Delphi repositories that interacted with the SOAP services.
Or
You could just as easily move the POCOs (and code generation) to a separate project, change your DataAccessLayer library to reference the POCOs library and only contain the Db context made up of DbSets of your POCOs, and Data access logic but no entities (which are now POCOs). Your clients will not need to have a dependency on the DataAccessLayer library.
So... a good solution, depending on your constraints.

Structuring/architecting an Azure Mobile Apps Service Entity Framework Code-First and .NET APK project

I am an experienced .NET/C# developer but new to pretty much all of the technologies/libraries here including SQL/DB work.
I am developing a project with an Azure/Entity Framework .NET backend and portable .Net APK for consumption in a number of other projects. I am trying to follow recommended practices and guidelines, but it's surprisingly hard to find documentation. I find myself repeatedly feeling like I'm fighting against the system, and slowly beating out a seemingly endless succession of fires with a blunt table spoon.
I find myself wondering if the overall architecture I'm using is the fundamental problem here. I prefer to pretend I'm not merely incompetent.
Current Structure
DTO contracts project
Interfaces for the DTO classes shared between the other two projects
Backend project
Implementations of the DTO interfaces + conversion to/from model classes
Code first database model classes
TableController<SOME_DTO_CLASS> implementations
ApiController for non-query operations
Portable SDK library project
Implementations of the DTO interfaces + conversion to/from SDK classes
SDK exposed classes for use from other applications
Service class that wraps MobileServiceClient and IMobileServiceTable and exposes SDK classes
Motivation/Implementation
Contract interfaces
The motivation for the DTO contract interfaces is to get as far away from magic strings / relying on member names as possible. These are interfaces rather than classes because TableController<T> requires implementations of ITableData, which is not available for use in the portable DTO contracts project.
Backend
The TableController<SOME_DTO_CLASS> classes GET methods currently refer to the current context (NOT this.Query()) and .Select() to create matching instances of the DTO classes. Lazy-loading is intact. These GET methods apply a .Where() with this.User to filter out only those entities the user has permission to access.
The Code-First model entirely derives from EntityData, even if the class is not going to be exposed via a TableController<T>. Navigation properties are used to types that are NOT exposed via their own TableController<T>. The fluent API is used to describe relationships.
The DTO classes expose their relation properties as the interface types rather than their concrete types because that's how interfaces work.
SDK
Currently this uses IMobileServiceTable but will likely switch over to IMobileServiceSyncTable at some point.
The DTO classes expose their relation properties as the interface types rather than their concrete types because that's how interfaces work.
Current flaming spoon target
Right now I've got the SDK successfully exposing it's own SDK types pulled down from the database. DB model -> DB DTO --> *MS Code* --> SDK DTO -> SDK exposed class all works.
Sort of.
The DB DTO classes' properties that expose other DB DTO classes appear to be ignored in transmission despite being part of the IQueryable returned in the GET method. I cannot retrieve them using $expand= as apparently The specified type member 'TestClass' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported. This still occurs if I switch from interface property types to concrete ones.
I could potentially avoid this issue by only including foreign key IDs and fetching linked entities separately in the SDK, but that seems highly inefficient and somewhat very nope.
Get to the question you 4AM fool!
Dis gud?
More specifically (and formally) is this current project structure reasonable and likely to be sustainable? Are there any obvious flaws or oversights that will prevent this from working?
Assuming this is reasonably reasonable, what is the proper way to tackle the DTO $expand issue?
The $expand attribute is the way to go, but unfortunately the Azure Mobile client SDK blocks this in the query string. It will be fixed in the future, but for right now your best bet is to use an attribute on the server side to add the query string on incoming requests.
For an example of this, see https://github.com/paulbatum/FieldEngineerLite/blob/master/FieldEngineerLite.Service/Helpers/ExpandPropertyAttribute.cs. The sample is for Azure Mobile Services, but that code can be easily applied to the Azure Mobile Apps server SDK.

Two (almost) concurrent DbContexts causing problems: How to share between Controller and AuthorizeAttribute

Every once in a while, I'm encountering the following exception in my ASP.NET/MVC5/WebAPI2/EF6/MSSQL application:
System.InvalidOperationException: The context cannot be used while the model is being created. This exception may be thrown if the context is used inside the OnModelCreating method or if the same context instance is accessed by multiple threads concurrently. Note that instance members of DbContext and related classes are not guaranteed to be thread safe.
I've traced this to my authorization code, which is a derivative of AuthorizeAttribute and instantiating its own DbContext to verify that my Web API consumer's API key is valid (the error occurs when trying to access the database).
The AuthorizeAttribute in turn decorates controllers which are derivatives of my BaseController, which also instantiates a DbContext for controller work.
After trying to troubleshoot this for days and reading this and this I suspect that creating the two DbContext instances per request is the problem. However, I'm not quite sure how I can use only a single instance for this work. My controller code currently nicely instantiates the DbContext upon its own creation and disposes of it transparently when the controller itself disposes. The AuthorizeAttribute is completely independent from all this and creates the context on demand for its own purposes.
Any patterns/ideas how to preserve/reuse the same DbContext for both units of work?
I had exactly the same issue when starting out with a base application using Entity Framework 6 for the first time.
The best solution for me was to ensure only one DbContext instance during the request life cycle using Autofac (with MVC integration) and Autofac's InstancePerRequest lifetime scope.
If you're interested in going down the dependency injection route (which I'd strongly advise) I would recommend familiarizing yourself with Autofac - and for more information on your particular issue check out davidbitton's answer here - it will get you on the right track.