Using Entity Framework in Console Application
In this post, we shall learn how to use Entity Framework in a Console application in the .NET Core. We shall scaffold the existing database and then leverage Generic HostBuilder to register the DBContext objects in the IoC container and then use it to perform CRUD operation on the database.
We shall also see consuming DBContext objects without Dependency injection (DI).
Today in this article, we will cover below aspects,
We already looked at how to Use a generic host builder for Dependency injection in .NET Core console applications.
Let’s look into how to use generic HostBuilder to create DI Container and inject the required dependency within the Console app .NET Core application.
Getting started
Here I am using .NET Core 3.1 Console application,
Similar to the already discussed article in the previous post on DI here is the project structure we shall be dealing with is same. I shall be using the same sample and performing DI but we will be using .NET Core 3.1.
The early structure will give you an idea of what we will achieve towards the end of this article.
For complete sample code for the above application kindly refer below article,
Creating Generic HostBuilder
The HostBuilder class is available from the following namespace,
using Microsoft.Extensions.Hosting;
HostBuilder implements the IHostBuilder interface.
Please install the NuGet package from Nuget Package manager or PMC,
PM> Install-Package Microsoft.Extensions.Hosting -Version 3.1.1
Create DI Container and Initialize Host
Please create Generic HosBuilder and register the dependencies that need to inject. These changes can be implemented in the Main() method.
var builder = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.AddLogging(configure => configure.AddConsole())
.AddTransient<MyApplication>()
.AddScoped<IBusinessLayer, BusinessLayer>()
.AddSingleton<IDataAccessLayer, CDataAccessLayer>()
.AddDbContext<EmployeeContext>(options =>
{
options.UseSqlServer("Server=localhost\\SQLEXPRESS;Database=master;Trusted_Connection=True;");
});
}).UseConsoleLifetime();
var host = builder.Build();
MyApplication class as the entry point for all business functionalities.
EmployeeContext is generated using EntityFrameworkCore scaffolding tool which is discussed below.
We shall be consuming EmployeeContext within DataAccess Layer but if you don’t have another module, you can use it using Constructor injection in any class of your choice.
Creating EmployeeContext using EFCore Tools
EFCore Package Manager Console Tool can be installed by using below Nuget package within the project directory,
PM> Install-Package Microsoft.EntityFrameworkCore.Tools
Please install below additional Nuget packages in the application,
- “Microsoft.EntityFrameworkCore”
- “Microsoft.EntityFrameworkCore.Design”
- “Microsoft.EntityFrameworkCore.SqlServer”
Create Scaffolding for Database
Below is the database schema we shall be using for performing CRUD operation,
Use the below commands to scaffold the database as below
PM> Scaffold-DbContext "Server=localhost\SQLEXPRESS;Database=master;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer
The above commands shall add all the required scaffolding including DbContext and model entities to the applications.
You can Create the scaffolding for one or multiple tables depending on the requirements.
Using EmployeeContext within Repository or Data Access Layer
EmployeeContext can be initialized within the Data Access Layer using Constructor injections.
Below shows a Create method where we are inserting a record to the database. On a similar line, you can add other CRUD methods as required.
public class CDataAccessLayer : IDataAccessLayer
{
private readonly ILogger _logger;
private readonly EmployeeContext _employeeContext;
public CDataAccessLayer()
{
}
public CDataAccessLayer(ILogger<CDataAccessLayer> logger, EmployeeContext context)
{
_logger = logger;
_employeeContext = context;
}
public void Create(EmployeeDb employeeDB)
{
try
{
_logger.LogInformation("DataAccessLayer {DataAccessLayerEvent} at {dateTime}", "Started", DateTime.UtcNow);
//Perform CRUD operation here
_employeeContext.EmployeeDb.Add(employeeDB);
_employeeContext.SaveChangesAsync();
_logger.LogInformation("DataAccessLayer {DataAccessLayerEvent} at {dateTime}", "Ended", DateTime.UtcNow);
}
catch (Exception ex)
{
//Log technical exception
_logger.LogError(ex.Message);
string error = ex.Message;
//Return Business exception repsponse here
throw new Exception("Error Invalid oepration performed {error}");
}
}
}
Initialize the CreateScope
Please add below code in the Main() method,
using (var serviceScope = host.Services.CreateScope()) { var services = serviceScope.ServiceProvider; try { var myService = services.GetRequiredService<MyApplication>(); await myService.Run(); Console.WriteLine("Success"); } catch (Exception ex) { Console.WriteLine("Error Occured"); } }
Below is the class MyApplication executing the business workflow.
We are injecting logger and business objects as defined and registered in the scope using the HostBuilder DI container.
public class MyApplication { private readonly ILogger _logger; private readonly IBusinessLayer _business; public MyApplication(ILogger<MyApplication> logger, IBusinessLayer business) { _logger = logger; _business = business; } internal async Task Run() { _logger.LogInformation("Application {applicationEvent} at {dateTime}", "Started", DateTime.UtcNow); _business.PerformBusiness(); _logger.LogInformation("Application {applicationEvent} at {dateTime}", "Ended", DateTime.UtcNow); Console.WriteLine("PRESS <ENTER> TO EXIT"); Console.ReadKey(); } }
Using DBContext without Dependency Injection
Above IoC usage of DBContext takes care of creating DBContext as and when needed. Framework based IoC containers also dispose of those objects when their usage is done.
If you do not want to use DI, it pretty straight forward to use DBContext anywhere in the project.
In fact, EmployeeContext becomes accessible in your module by adding below the line of code. Please add the required using references.
Let’s execute the application and capture the event and action,
- References: DBContext Scaffolding commands in .NET Core
That’s all! Happy coding
Summary
In this post, we learned how to use Entity Framework Core in a Console application in the .NET Core. We learned how to scaffold the existing database and then leverage Generic HostBuilder to register the DBContext objects in the IoC container. We also looked at how to use DBContext objects in a Console application without Dependency Injection.
Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.
Hi,
I’ve tried creating a scope to resolve a concurrency issue with the DbContext in “MyApplication”, but it still has the same issue with collisions in the context as it’s not thread safe.
Am I right in saying that I would need to create a scope per thread? I would require quite a restructure of my app to make that change so that’s why I haven’t tested it yet!
Cheers
Dave
Hey Dave- Thanks for your query. Please make sure services that use DBCOntext vis DI also has the same lifespan as of DBContext or vice versa. Yes, DBContext is not thread-safe and an instance can be used per scope as per my understanding by proper lifespan using DI. Would be a great help if you can update once you are able to resolve the issue with the approach you following .References