Thoughts on .NET Core 6.0, Entity Framework and the New MVC Pattern
The following mostly doesn't refer to problems native to the .NET Core 6 Framework itself, but rather some difficulties I encountered while getting an Entity Framework Database-First model working in the MVC project template generated by Visual Studio 2022.
Some of the problems centred around:
Breaking changes and things that might be awkward for developers accustomed to working with legacy non-Core versions of .NET (espectially .NET MVC).
Not much documentation out there, relative to what's published for the older .NET MVC patterns.
Apparently not many developers having worked with it yet.
A heavy amount of dependency injection included in the later MVC code patterns. This occasionally made it considerably more difficult to trace errors, and would present a learning curve for less experienced developers.
MVC Project Changes
When the ASP.NET MVC project template is set up by Visual Studio, the code patterns and source file structure are going to be different to what was generated by previous versions. The main three differences are a) a heavy amount of dependency injection, b) the Web.config has been replaced by an appsettings.json file and Startup.cs has been replaced by Program.cs (the code pattern here is also different), and c) The method for setting up an Entity Framework model, DbContext and data source connection is different.
Database-First Entity Framework Model
The first problem is that Visual Studio won't scaffold the application to use Entity Framework or DbContext, and there isn't an Entity Framework model designer. A partial solution is to run the following in NuGet Package Manager Console:
Install-Package Microsoft.EntityFrameworkCore.Tools
And:
Scaffold-DbContext "Server=.\SQLExpress;Database=emmatest;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models
Click here for further information about this and related tools...
I recommend this method, as it will save a considerable amount of time setting up the model, and it should be a more reliable way of applying the correct data types.
In addition to the model, the script will also create a DbContext class. This will need to be modified, if not rewritten. One reason for this is the connection string must be moved into appsettings.json. The following was my rewrite of DbContext:
using Microsoft.EntityFrameworkCore;
using WebApplication8.Models;
namespace WebApplication8.Data
{
public class ApplicationDbContext : DbContext
{
protected readonly IConfiguration Configuration;
public ApplicationDbContext(DbContextOptions<DbContext> options) : base(options)
{
}
public ApplicationDbContext(IConfiguration configuration)
{
Configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
// connect to sql server with connection string from app settings
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
}
public DbSet<Computer> Computers { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<Lab> Labs { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<WebApplication8.Models.Computer>()
.ToTable("computer");
}
}
}
Connection String
Insert the following in the appsettings.json file:
"ConnectionStrings": {
"DefaultConnection": "Server=EMMA-LAPTOP\\SQLEXPRESS;Initial Catalog=emmatest;Integrated Security=True"
},
Here I've included the local machine's name in the connection string, as I might be running the application from within a Docker container.
Program.cs
In Program.cs, add the following:
builder.Services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
});
Make sure to add it before the var app = builder.Build();
statement.
At this point, we could use SQL Server Profiler to check whether the application is reading from the database. (SQL Server Management Studio -> Tools -> SQL Server Profiler)
Data Validation
It's a good idea to apply data validation to the model itself. In the model class file, add the following reference:
using System.ComponentModel.DataAnnotations;
Razor Views
Obviously pretty much the same as with the older MVC pattern:
@model IEnumerable<Test_MVC.Models.Computer>
Using DbContext in the Controller
Assuming we're just using the DbContext model without a Unit of Work Repository pattern:
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using WebApplication8.Models;
using WebApplication8.Data;
private readonly ApplicationDbContext _context;
public HomeController(ApplicationDbContext context)
{
_context = context;
}
In the controller method:
public IActionResult Index()
{
var model = _context.Computers.ToList();
return View(model);
}
Further Information
Microsoft Docs: Breaking Changes in .NET 6
Entity Framework Core tools reference - Package Manager Console in Visual Studio