Getting Start with Entity Framework Core 3.1 – Part VI

Introduction:

So far in this series we have seen the concepts/features of Entity framework core. In this blog I’m going to explain about how to integrate Entity Framework project in to ASP.NET Core Web API application.  

This is a continuation of my last blog.

Create a New ASP.NET Core Web API Application:

Step 1: Right click on the Solution and select Add-> New Project

Step 2: From the wizard choose ASP.NET Core Web application template.

Figure 1: ASP.NET Core Web Application

Step 3: Provide a project name.

Figure 2: Project Name

Step 4: Select API Project template and save.

Figure 3: API Project Template

Step 5: Run the application you can see the JSON result, a output from the weather forecast API, which is already defined in the project by default.

Figure 4: Weather Forecast Response

Note: Make the API project as a startup project.

Add User Controller to the Project :

Step 1: Add Domain and Data project references to the AspWebAppCore Project.

Figure 5: Reference Manager

Step 2: Build solution

After adding the references it’s really important to build the solution

Step 3: Add a new controller

Right click on the controller folder and select Add-> Controller. Select API Controller with actions, using Entity Framework template and click on next.  

Figure 6: Controller Template

Provide Model class and Data context class, and all the magic 😊 (scaffolding) happens when you click on Add. It will install all the necessary packages while scaffolding.

Figure 7: Add Controller

The new UsersController class has been added with some predefined API actions in the controller.

 Step 4: Modify the Package

Open the project file, you can observe the list of EF packages which are added while doing a scaffolding.

Figure 8: Project File

Here I replaced the SqlLite package to SqlServer, since we are going to use the SqlServer provider for EFCore.

UsersController.cs

        [HttpGet]
        public async Task<ActionResult<IEnumerable<User>>> GetUsers()
        {
            return await _context.Users.ToListAsync();
        }

GetUsers() action is used to retrieve all the Users.

        // GET: api/Users/5
        [HttpGet("{id}")]
        public async Task<ActionResult<User>> GetUser(int id)
        {
            var user = await _context.Users.FindAsync(id);

            if (user == null)
            {
                return NotFound();
            }

            return user;
        }

GetUser() action is used to retrieve the user based in UserId Key.

[HttpPut("{id}")]
        public async Task<IActionResult> PutUser(int id, User user)
        {
            if (id != user.Id)
            {
                return BadRequest();
            }

            _context.Entry(user).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!UserExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return NoContent();
        }

PutUser() action is used to update the user.

[HttpPost]
        public async Task<ActionResult<User>> PostUser(User user)
        {
            _context.Users.Add(user);
            await _context.SaveChangesAsync();

            return CreatedAtAction("GetUser", new { id = user.Id }, user);
        }

PostUser() action is used to create a new user.

[HttpDelete("{id}")]
        public async Task<ActionResult<User>> DeleteUser(int id)
        {
            var user = await _context.Users.FindAsync(id);
            if (user == null)
            {
                return NotFound();
            }

            _context.Users.Remove(user);
            await _context.SaveChangesAsync();

            return user;
        }

DeleteUser() action is used to delete a user.

  private bool UserExists(int id)
        {
            return _context.Users.Any(e => e.Id == id);
        }

UserExists() action is used to check the user existence.

Wiring up ASP.NET Core App with DbContext:

Step 1: Add services.DbContex with UseSqlServer() to startup Configure()

Open Startup.cs file and add the below code in ConfigureService() method.

public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddDbContext<AppDBContext>(option => option
            .UseSqlServer(Configuration.GetConnectionString("AppConnection"))
            .EnableSensitiveDataLogging());
        }

By Default, the ASP.NET uses Dependency injection to interact with another feature. It manages from ASP.NET Core services as well as the logging feature also will be configured by default.

Add the namespace using Microsoft.EntityFrameworkCore.

Provide the SQL connection string information in appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information",
      "Microsoft.EntityFrameworkCore.Database.Command": "Information"
    }
  },
  "ConnectionStrings": {
    "AppConnection": "Data Source=DESKTOP-585QGBN;Initial Catalog =EFCoreDemoDB; Integrated Security=SSPI"
  },
  "AllowedHosts": "*"
}

From the above code you can observe with default logging setup we also added one more information to log SQL Command generated by EF Core.

Add Constructor for DB Context

Step 1: Open AppDBContext.cs file from the Data project and add the below code.

 public AppDBContext(DbContextOptions<AppDBContext> options):base(options)
        {
            ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
        }

Why do we need to add a constructor in AppDBContext.cs?

Because the controller use AppDbContext instance and it expect the instance to be passed to its constructor, which means the AppDbContext should be instantiate before the controller instantiate. I hope now you can understand why we configured the AppDBContext in Startup file , that configuration tells ASP.NET Core to instantiate the AppDBContext whenever the controller needs it.

Since our application behaves as a disconnected client, which means for each HTTP call the new controller and AppDbContext gets initiated so the context tracking is really not necessary. By disabling this feature will help to improve the performance.

Remove OnConfiguring() method and loggerFactory from AppDBContext.cs

Step 2: Run the application and call User API

Figure 9: User API Response

As expect the api/Users API returns List of users in AppDbContext.

Figure 10: SQL Command

From the above image you can observe the SQL Command which is generated by EF Core while fetching the Users details.

Summary:

I hope this blog really helps you to understand how to integrate the Entity framework core to your ASP.NET Core web application project by following a key steps as mentioned below.

  • Wiring up the ASP.NET Core web app with DbContext
  • Adding Constructor to the DbContext class and understanding about Dependency Injection.
  • Improving the performance by disabling the context tracking.

Source Code – https://github.com/gowthamece/EFCore

Happy Coding!!!

gowthamk91

Leave a Reply

%d bloggers like this: