Using Entity Framework Core Code First Approach

Introduction

 
In this post, we will learn about to Entity Framework core and implement it in .NET Core API. The .Net Core API application has been explained in the below post.
 

About Entity Framework Core

 
Entity Framework Core is a modified version of the existing “Entity Framework” library which has extensible, lightweight, and cross-platform support. It supports relational and Non-relational databases. It also supports the “Code First” or “Database First” approach as a programming model.
 
Step 1
 
We will create Entities, which are regular C# classes with DB attributes. Entities are not “DTO” objects because it's designed for Database interactions. We will be using the code-first approach, so these Entity classes are inputs for DB creation.
 
Address Entity
 
publicclass Address
  1.    {  
  2.        [Key]  
  3.        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]  
  4.        public int Id { getset; }  
  5.        public string AddressDetail { getset; }  
  6.        [ForeignKey("EmployeeId")]  
  7.        public Employee Employee { getset; }  
  8.   
  9.        public int EmployeeId { getset; }  
  10.    }  
 Employee Entity
  1. public class Employee  
  2.     {  
  3.         [Key]  
  4.         [DatabaseGenerated(DatabaseGeneratedOption.Identity)]  
  5.         public int Id { getset; }  
  6.         public string EmployeeName { getset; }  
  7.         public string Skill { getset; }  
  8.         public string Email { getset; }  
  9.   
  10.         public ICollection<Address> EmployeeAddress { getset; }  
  11.                     = new List<Address>();  
  12.     }  
Step 2
 
We need to add install a few NuGet packages to work with EntityFrameworkCore and SQL server and install the below packages.
 
NuGet Packages required
  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.Tools
  • Microsoft.EntityFrameworkCore.SqlServer 
Step 3
 
We need to add the “DbContext” file to our application. According to Microsoft definition, “A ‘DbContext’ instance represents a session with the database and can be used to query and save instances of your entities. “DbContext” is a combination of the ‘Unit Of Work’ and Repository patterns”.
 
Create a “Contexts” folder and class file “EmployeeDbContext” that derives from the “DbContext” base class. This base class is as part of “Microsoft.EntityFrameworkCore” and we need to install EntityFrameworkCore NuGet package.
 
Add below “DBSet” to our “EmployeeDbContext” class. 
  1. public DbSet<Employee> Employees { getset; }  
  2. public DbSet<Address> Addresses { getset; }  
We will add the below constructor to override DbContextOptions to ensure that the db is created before any db operation in our application. This code will ensure that the db will be created in Step5. 
  1. public EmployeeDbContext(DbContextOptions<EmployeeDbContext> options)  
  2.             :base(options)  
  3.         {  
  4.             Database.EnsureCreated();  
  5.         }  
Step 4
 
We need to add the below code in “Startup.cs” -> “configureServices” method. Registering “EmployeeContext” and Configures the context to connect to a Microsoft SQL Server database.
  1. services.AddDbContext<EmployeeDbContext>(o=>  
  2.             {  
  3.                 o.UseSqlServer(_configuartion["connectionStrings:EmployeeDbConnectionString"]);  
  4.             });  
Step 5
 
In “EmployeeController” inject the “EmployeeContext” context and run the application. Run the application now and the “EmployeeDetails” Database created with 2 tables.
 
Using Entity Framework Core Code First Approach
 
Step 6
 
Before we add “Seed” data, we will make sure the existing database got deleted and create a new database every time. We can change this option based on our requirements. Add the below code “Program.cs” file. Refer to Step 10 for the complete code. 
  1. context.Database.EnsureDeleted();  
  2. context.Database.Migrate();  
Step 7
 
We will add some “Seed” data to our database, which means when we create a new database and tables, we will add some sample data to the tables instead of empty tables.
 
Override “OnModelCreating” method in “EmployeeDbContext” class and the below sample data. Refer to Step 10 for the complete code. 
  1. modelBuilder.Entity<Employee>()  
  2.                .HasData(  
  3.                new Employee()  
  4.                {  
  5.                    Id = 1,  
  6.                    EmployeeName = "Test Emp1",  
  7.                    Email = "Test@test.com",  
  8.                    Skill = "Test1"  
  9.                },  
  10.                 new Employee()  
  11.                 {  
  12.                     Id = 2,  
  13.                     EmployeeName = "Test Emp2",  
  14.                     Email = "Test@test.com",  
  15.                     Skill = "Test1"  
  16.                 },  
  17.                  new Employee()  
  18.                  {  
  19.                      Id = 3,  
  20.                      EmployeeName = "Test Emp3",  
  21.                      Email = "Test@test.com",  
  22.                      Skill = "Test1"  
  23.                  });  
Step 8
 
Open the “Package Manager Console” and run the Add-Migration command.
 
Using Entity Framework Core Code First Approach
 
This will create a Migrations folder and “FirstMigration.cs” auto-generated file. This class file has “Up” and “Down” methods to create or delete schema objects.
 
Using Entity Framework Core Code First Approach
 
Step 9
 
After running the application, we will see our “Seed” data has been inserted in both tables.
 
Using Entity Framework Core Code First Approach
 
Using Entity Framework Core Code First Approach
 
Step 10
 
After running the following codes, for your reference check below:
 
Program.cs
  1. public static void Main(string[] args)  
  2.         {  
  3.             var host = CreateHostBuilder(args).Build();  
  4.   
  5.             using (var scope = host.Services.CreateScope())  
  6.             {  
  7.                 try  
  8.                 {  
  9.                     var context = scope.ServiceProvider.GetService<EmployeeDbContext>();  
  10.                     context.Database.EnsureDeleted();  
  11.                     context.Database.Migrate();  
  12.                 }  
  13.                 catch (Exception)  
  14.                 {  
  15.                     throw;  
  16.                 }  
  17.             }  
  18.             host.Run();  
  19.         }  
Startup.cs
  1. public class Startup  
  2.    {         
  3.        private readonly IConfiguration _configuartion;    
  4.        public Startup(IConfiguration configuartion)  
  5.        {  
  6.            _configuartion = configuartion;  
  7.        }    
  8.        public void ConfigureServices(IServiceCollection services)  
  9.        {  
  10.            services.AddMvc();  
  11.            services.AddScoped<IEmployeeRepository, EmployeeTestRepository>();  
  12.   
  13.            services.AddDbContext<EmployeeDbContext>(o=>  
  14.            {  
  15.                o.UseSqlServer(_configuartion["connectionStrings:EmployeeDbConnectionString"]);  
  16.            });  
  17.        }    
  18.        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.  
  19.        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)  
  20.        {  
  21.            if (env.IsDevelopment())  
  22.            {  
  23.                app.UseDeveloperExceptionPage();  
  24.            }  
  25.         
  26.            app.UseRouting();  
  27.   
  28.            app.UseEndpoints(endpoints =>  
  29.            {  
  30.                endpoints.MapControllers();  
  31.            });  
  32.        }  
  33.    }  
EmployeeController.cs
  1. [ApiController]  
  2.     [Route("api/[controller]")]  
  3.     public class EmployeeController : ControllerBase  
  4.     {  
  5.   
  6.         private readonly ILogger<EmployeeController> _logger;  
  7.         private readonly IEmployeeRepository _employeeRepository;  
  8.         private readonly EmployeeDbContext _context;  
  9.   
  10.         public EmployeeController(ILogger<EmployeeController> logger, IEmployeeRepository employeeRepository, EmployeeDbContext context)  
  11.         {  
  12.             _logger = logger;  
  13.             _employeeRepository = employeeRepository;  
  14.             _context = context;  
  15.         }  
  16.          
  17.         // GET: api/<controller>  
  18.         [HttpGet]  
  19.         public IActionResult Get()  
  20.         {  
  21.             var result = GetEmployees();  
  22.   
  23.             if (result==null)  
  24.             {  
  25.                 return NotFound();  
  26.             }  
  27.   
  28.             return Ok(result);  
  29.         }  
  30.         private List<EmployeeModel> GetEmployees()  
  31.         {  
  32.             return _employeeRepository.GetAllEmployee();  
  33.         
EmployeeDbContext.cs
  1. public class EmployeeDbContext: DbContext  
  2.     {         
  3.         public DbSet<Employee> Employees { getset; }  
  4.         public DbSet<Address> Addresses { getset; }  
  5.   
  6.         protected override void OnModelCreating(ModelBuilder modelBuilder)  
  7.         {  
  8.             modelBuilder.Entity<Employee>()  
  9.                 .HasData(  
  10.                 new Employee()  
  11.                 {  
  12.                     Id = 1,  
  13.                     EmployeeName = "Test Emp1",  
  14.                     Email = "Test@test.com",  
  15.                     Skill = "Test1"  
  16.                 },  
  17.                  new Employee()  
  18.                  {  
  19.                      Id = 2,  
  20.                      EmployeeName = "Test Emp2",  
  21.                      Email = "Test@test.com",  
  22.                      Skill = "Test1"  
  23.                  },  
  24.                   new Employee()  
  25.                   {  
  26.                       Id = 3,  
  27.                       EmployeeName = "Test Emp3",  
  28.                       Email = "Test@test.com",  
  29.                       Skill = "Test1"  
  30.                   });    
  31.   
  32.             modelBuilder.Entity<Address>()  
  33.                 .HasData(  
  34.                 new Address()  
  35.                 {  
  36.                     Id = 1,  
  37.                    AddressDetail="Test Address1",  
  38.                    EmployeeId=1  
  39.                 },  
  40.                   new Address()  
  41.                   {  
  42.                       Id = 2,  
  43.                       AddressDetail = "Test Address2",  
  44.                       EmployeeId = 2  
  45.                   },  
  46.                    new Address()  
  47.                    {  
  48.                        Id = 3,  
  49.                        AddressDetail = "Test Address3",  
  50.                        EmployeeId = 1  
  51.                    });  
  52.   
  53.             base.OnModelCreating(modelBuilder);  
  54.         }  
  55.   
  56.         public EmployeeDbContext(DbContextOptions<EmployeeDbContext> options)  
  57.             :base(options)  
  58.         {  
  59.             Database.EnsureCreated();  
  60.         }            
  61.     }  

Summary

 
In this post, we learned about Entity Framework Core and sample database creation with seed data using the code-first approach.
 
The .NET Core API application has been explained in the following post.