[ASP.NET Core][EntityFramework Core] Update from .NET 5 to .NET 6
Masui Masanori
Posted on December 6, 2021
Intro
Congratulations on the release of .NET 6 !
I want to update ASP.NET Core projects what are made in .NET 5 to .NET 6.
Environments
- .NET ver.5.0.202 -> .NET ver.6.0.100
Sample project
I use a project what I created for trying signing in from Blazor pages.
ApprovementWorkflowSample.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog.Web.AspNetCore" Version="4.10.0"/>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.2"/>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.2"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.2"/>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3"/>
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.2"/>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.2"/>
</ItemGroup>
</Project>
Program.cs
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog.Web;
namespace ApprovementWorkflowSample
{
public class Program
{
public static void Main(string[] args)
{
var logger = NLogBuilder.ConfigureNLog("Nlog.config").GetCurrentClassLogger();
try
{
CreateHostBuilder(args).Build().Run();
}
catch (Exception ex) {
logger.Error(ex, "Stopped program because of exception");
throw;
}
finally {
NLog.LogManager.Shutdown();
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureLogging((hostingContext, logging) =>
{
logging.ClearProviders();
logging.SetMinimumLevel(LogLevel.Trace);
})
.UseNLog();
}
}
Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using ApprovementWorkflowSample.Applications;
using ApprovementWorkflowSample.Models;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server;
using ApprovementWorkflowSample.Approvements;
namespace ApprovementWorkflowSample
{
public class Startup
{
private readonly IConfiguration configuration;
public Startup(IConfiguration configuration)
{
this.configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddHttpClient();
services.AddControllers()
.AddNewtonsoftJson();
services.AddDbContext<ApprovementWorkflowContext>(options =>
options.UseNpgsql(configuration["DbConnection"]));
services.AddIdentity<ApplicationUser, IdentityRole<int>>()
.AddUserStore<ApplicationUserStore>()
.AddEntityFrameworkStores<ApprovementWorkflowContext>()
.AddDefaultTokenProviders();
services.AddScoped<IHostEnvironmentAuthenticationStateProvider>(sp =>
(ServerAuthenticationStateProvider) sp.GetRequiredService<AuthenticationStateProvider>()
);
services.AddScoped<IApplicationUsers, ApplicationUsers>();
services.AddScoped<IWorkflows, Workflows>();
services.AddScoped<IApplicationUserService, ApplicationUserService>();
services.AddScoped<IApprovementService, ApprovementService>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapControllers();
});
}
}
}
Update to .NET 6
To update the project to .NET 6, I change "ApprovementWorkflowSample.csproj" first.
ApprovementWorkflowSample.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog.Web.AspNetCore" Version="4.14.0"/>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.1"/>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.0"/>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1"/>
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.0"/>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.0"/>
</ItemGroup>
</Project>
Before .NET 5 or earlier, I had had to changed some code after restoring.
But in this time, I don't need to change anything.
Merge "Startup.cs" into "Program.cs"
If I create a new .NET 6 project, it doesn't have "Startup.cs" and "Program.cs" doesn't have a class.
Program.cs (mvc template)
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
Program.cs
using ApprovementWorkflowSample.Models;
using ApprovementWorkflowSample.Applications;
using ApprovementWorkflowSample.Approvements;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server;
using NLog.Web;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
var logger = NLogBuilder.ConfigureNLog("Nlog.config").GetCurrentClassLogger();
try
{
var builder = WebApplication.CreateBuilder(args);
builder.Host.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
})
.UseNLog();
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddHttpClient();
builder.Services.AddControllers()
.AddNewtonsoftJson();
builder.Services.AddDbContext<ApprovementWorkflowContext>(options =>
options.UseNpgsql(builder.Configuration["DbConnection"]));
builder.Services.AddIdentity<ApplicationUser, IdentityRole<int>>()
.AddUserStore<ApplicationUserStore>()
.AddEntityFrameworkStores<ApprovementWorkflowContext>()
.AddDefaultTokenProviders();
builder.Services.AddScoped<IHostEnvironmentAuthenticationStateProvider>(sp =>
(ServerAuthenticationStateProvider) sp.GetRequiredService<AuthenticationStateProvider>()
);
builder.Services.AddScoped<IApplicationUsers, ApplicationUsers>();
builder.Services.AddScoped<IWorkflows, Workflows>();
builder.Services.AddScoped<IApplicationUserService, ApplicationUserService>();
builder.Services.AddScoped<IApprovementService, ApprovementService>();
// I can't do this before setting "WebApplicationBuilder".
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapControllers();
});
app.Run();
}
catch (Exception ex) {
logger.Error(ex, "Stopped program because of exception");
}
finally {
NLog.LogManager.Shutdown();
}
- Announcing .NET 6 — The Fastest .NET Yet - .NET Blog
- What's new in ASP.NET Core 6.0 | Microsoft Docs
- Comparing WebApplicationBuilder to the Generic Host: Exploring .NET Core 6 - Part 2 | Andrew Lock
- Logging in .NET Core and ASP.NET Core | Microsoft Docs
DateTime (EntityFramework Core + Npgsql)
From .NET 6, the data types of date and time have been changed.
And I got an exception when I insert data.
ApplicationUser.cs
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.AspNetCore.Identity;
namespace ApprovementWorkflowSample.Applications
{
public class ApplicationUser: IdentityUser<int>
{
...
[Required]
[Column("last_update_date", TypeName = "timestamp with time zone")]
public DateTime LastUpdateDate { get; set; }
...
public void Update(string userName, string? organization,
string email, string password)
{
UserName = userName;
Organization = organization;
Email = email;
// set hashed password text to PasswordHash.
PasswordHash = new PasswordHasher<ApplicationUser>()
.HashPassword(this, password);
// Get error
LastUpdateDate = DateTime.Now;
}
...
}
}
Error
InvalidCastException: Cannot write DateTime with Kind=Local to PostgreSQL type 'timestamp with time zone', only UTC is supported. Note that it's not possible to mix DateTimes with different Kinds in an array/range. See the Npgsql.EnableLegacyTimestampBehavior AppContext switch to enable legacy behavior.
So I had to convert to Universal time.
ApplicationUser.cs
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.AspNetCore.Identity;
namespace ApprovementWorkflowSample.Applications
{
public class ApplicationUser: IdentityUser<int>
{
...
[Required]
[Column("last_update_date", TypeName = "timestamp with time zone")]
public DateTime LastUpdateDate { get; set; }
...
public void Update(string userName, string? organization,
string email, string password)
{
UserName = userName;
Organization = organization;
Email = email;
// set hashed password text to PasswordHash.
PasswordHash = new PasswordHasher<ApplicationUser>()
.HashPassword(this, password);
// OK
LastUpdateDate = DateTime.Now.ToUniversalTime();
}
...
}
}
💖 💪 🙅 🚩
Masui Masanori
Posted on December 6, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.