ASP.NET Core Playground - 1. Setup
I have been obsessing about something since I started creating APIs in ASP.NET Core. I want to find the way to create a perfect endpoint. What makes things even more fun is that .NET 7 was just released so every blog post and document that describes best practices is no longer relevant, because everything changed!
I spent some time and created a micro laboratory for testing different cases and approaches, and this is how I did it.
Database
I set up a docker container with MS SqlServer 2022. Since at this moment I’m more on the Dev side of DevOps I used C# and FluentDocker
library to set everything up.
1
2
3
4
5
6
7
8
9
using Ductus.FluentDocker.Builders;
new Builder()
.UseContainer()
.UseImage("mcr.microsoft.com/mssql/server:2022-latest")
.WithEnvironment("SA_PASSWORD=ServerAdminPassword666", "ACCEPT_EULA=Y")
.ExposePort(1433, 1433)
.Build()
.Start();
Now I created a database using “Server Explorer” view in my Visual Studio 2022 and running a T-SQL script
1
CREATE DATABASE [PlaygroundDatabase]
I set database recovery mode to SIMPLE
to save hard drive space since we really don’t care about ensuring the data is recoverable in case of corruption.
1
2
USE [master]
ALTER DATABASE [PlaygroundDatabase] SET RECOVERY SIMPLE
Then created a table inside that database
1
2
3
4
5
6
7
USE [PlaygroundDatabase]
CREATE TABLE [dbo].[WeatherForecasts](
[Id] [uniqueidentifier] NOT NULL,
[Date] [datetime2](7) NOT NULL,
[TemperatureC] [int] NOT NULL,
[Summary] [nvarchar](max) NULL
)
And filled it with 100.000 rows of data that contained 10.000.000 characters long string. This makes the database just over 1.5GB in size and ensures a nice and observable delay between each row when sending the data to Entity Framework Core.
1
2
3
4
5
6
7
8
9
10
11
USE [PlaygroundDatabase]
DECLARE @I Int = 0
WHILE (@I < 100000)
BEGIN
INSERT INTO dbo.WeatherForecasts VALUES
(NEWID(), GETUTCDATE(), @I, (REPLICATE('X', 10000000)))
SET @I = @I + 1;
END
Backend
Now I created a simple WebAPI project with controllers, added Mapster and EntityFrameworkCore to it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Mapster" Version="7.3.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.1" />
</ItemGroup>
</Project>
This is the model I used
1
2
3
4
5
6
7
public class WeatherForecast
{
public Guid Id { get; set; }
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public string? Summary { get; set; }
}
together with a very basic DbContext class
1
2
3
4
5
6
7
8
public class CustomDbContext : DbContext
{
public DbSet<WeatherForecast> WeatherForecasts { get; set; } = null!;
public CustomDbContext(DbContextOptions<CustomDbContext> contextOptions) : base(contextOptions)
{
}
}
that I configured in Program.cs
this way
1
builder.Services.AddDbContext<CustomDbContext>(options => options.UseSqlServer("Server=localhost;Database=PlaygroundDatabase;User Id=sa;Password=ServerAdminPassword666;trustServerCertificate=true"));
I also added a DTO to be used in several different scenarios.
1
2
3
4
5
public class WeatherForecastDto
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
}