This sample solution makes use of ASP.NET Core with ASP.NET Identity over Entity Framework Core running side-by-side with Entity Framework 6. Look at this if you don’t want Entity Framework Core for your data layer, but still want to use ASP.NET Identity in ASP.NET Core and benefit from its out-of-the-box implementation (which is awesome!).
Goals and inspiration
I was inspired by Mosh Hamedani’s work on “Repository Pattern with C# and Entity Framework, Done Right“. I think the theory that Mosh has put forward on the difference between a repository pattern and EF’s DbContext is well structured and well explained. The sample code is also worth checking out.
I wanted to take it one step forward and put the pattern into an ASP.NET Core starter solution. The key point I want to demonstrate is using critical components of an ASP.NET Core MVC web application with an implementation of the repository that works side-by-side with the ASP.NET Identity 3 implementation. I wanted to make the repository asynchronous as well, because there’s not many good examples out there.
The catch: ASP.NET Identity 3 uses ASP.NET Core and Entity Framework Core. That’s all great, but many are not ready for EFCore and want the battle-tested Entity Framework 6. EF6 is feature packed, while EFCore is still very feature-limited.
In summary, this sample answers these questions:
- How do you inject an EF6 context with a connection string in the ASP.NET Core service collection?
- How do you run ASP.NET Identity on EFCore and the rest of the application on EF6?
- How do you properly implement the Repository pattern with EF6?
- How do you make your Repository async?
- How do you maintain one database for both your custom entities and ASP.NET Identity?
- How and where do you implement a Services layer?
- How do you make your Controller methods Async?
- How do you use Services with Controllers?
- How do you keep the connection string in one place.
GitHub Repository: https://github.com/OneBitSoftware/AspNetCore.Ef6.Identity3.StarterSolution
The Data class library
I’ve taken all data access classes in relation to EF6 and the Repository pattern in a separate class library. This library doesn’t do anything else apart from the responsibility of data access. Technically you can split it into more assemblies if your case makes sense.
There’s no need for me to describe the Repository implementation itself, because Mosh has done it very well. Follow his video or code sample for background knowlede. I am focusing on using it in an ASP.NET Core MVC application.
This is what my *.Data project looks like:
Asynchronous Repository
Many operations against Entity Framework 6 make sense to be asynchronous. You get the true benefit if the async chain goes all the way up to the controller. That is why my repository interface returns Task<T>.
public interface IRepository<TEntity> where TEntity: class
{
Task<TEntity> GetAsync(int id);
Task<IEnumerable<TEntity>> GetAllAsync();
Task<IEnumerable<TEntity>> FindAsync(Expression<Func<TEntity, bool>> match);
Task<TEntity> AddAsync(TEntity entity);
Task RemoveAsync(TEntity entity);
Task RemoveRangeAsync(IEnumerable<TEntity> entity);
}
The Web project
All of my other bits and pieces I have stuck in the MVC project. I have strictly kept to the empty ASP.NET Core MVP project structure – my Services and View models are here. I have not touched the ApplicationDbContext ASP.NET Identity DbContext class to allow for a quick start.
If you choose, you can break this project into more class libraries. In this sample I keep my MVC(S) Services where my ViewModels are, so Services return ViewModels, which also means that they encapsulate the Factory calls to map Models to ViewModels. If you wish, you can move that responsibility to the Controllers and have your Services return Models (and essentially move Services to their own library).
The Visual Studio tooling and specifically the MVC scaffolding is unfortunately designed (as of now) to have everything in one project, that is when you get good scaffolding possibilities.
Here is what my *.Web project looks like:
Common database for entities and ASP.NET Identity tables
Nobody wants to deal with more than one database unless it is really necessary. In our case we want a web application with objects and user accounts – not a hugely complex thing. A single database would be appropriate for many scenarios.
The sample does just that – both contexts (ApplicationDbContext and my custom entity context) access the same database. They use the same connection string during registration in the ConfigureServices startup method.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString(“DefaultConnection”)));
services.AddScoped<CarApplicationDbContext>(_ =>
new CarApplicationDbContext(Configuration.GetConnectionString(“DefaultConnection”)));
Here is what the database looks like. EF5 uses the migration history tables to deal with migrations as it should, the ContextKey column here is key.
Target Framework
Entity Framework 6 is dependent on the full .NET Framework. This is why the solution targets .NET Framework (4.5.2) but uses the ASP.NET Core framework and libraries to run the application.
Code on GitHub
Feel free to use as you please. I’d be glad to get your feedback and comments.
GitHub Repository: https://github.com/OneBitSoftware/AspNetCore.Ef6.Identity3.StarterSolution