diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml
index f941893..bcd8d51 100644
--- a/.github/workflows/build_test.yml
+++ b/.github/workflows/build_test.yml
@@ -16,7 +16,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
- dotnet-version: 7.0.x
+ dotnet-version: 8.0.x
- name: Install dotnet-ef
run: dotnet tool install --global dotnet-ef
diff --git a/Api/Api.csproj b/Api/Api.csproj
index 43bcf47..9897cbf 100644
--- a/Api/Api.csproj
+++ b/Api/Api.csproj
@@ -6,14 +6,11 @@
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
+
+
+
+
diff --git a/Api/Configuration/AddAndConfigureSwagger.cs b/Api/Configuration/AddAndConfigureSwagger.cs
index 6d10747..7e5c00f 100644
--- a/Api/Configuration/AddAndConfigureSwagger.cs
+++ b/Api/Configuration/AddAndConfigureSwagger.cs
@@ -2,14 +2,15 @@ namespace AK.DbSample.Api.Configuration;
internal static partial class ServiceCollectionExtensions
{
- public static void AddAndConfigureSwagger(this IServiceCollection services, IWebHostEnvironment env)
+ public static IServiceCollection AddAndConfigureSwagger(this IServiceCollection services, IWebHostEnvironment env)
{
if (env.IsProduction())
// No Swagger for PROD
- return;
+ return services;
- services.AddEndpointsApiExplorer();
- services.AddSwaggerGen(c => c.UseDateOnlyTimeOnlyStringConverters());
+ return services
+ .AddEndpointsApiExplorer()
+ .AddSwaggerGen();
}
public static void AddAppSwaggerUi(this IApplicationBuilder app, IWebHostEnvironment env)
diff --git a/Api/Startup.cs b/Api/Startup.cs
index 0f9121b..61d3e38 100644
--- a/Api/Startup.cs
+++ b/Api/Startup.cs
@@ -18,18 +18,10 @@ public Startup(IConfiguration config, IWebHostEnvironment hostEnvironment)
public void ConfigureServices(IServiceCollection services)
{
var settings = services.AddAndConfigureAppSettings(_configuration);
-
- services.AddAndConfigureDomainServices((settings.ConnectionString, true));
-
- // The below converters were required for .NET 6. Since .NET 7 they work out-of-the-box,
- // Swashbuckle is still lacking behind with the standard support, so need to keep these lines
- // till Swashbuckle NuGet gets updated.
- // Note: It'll also eliminate the need in DateOnlyTimeOnly.AspNet NuGet (https://github.com/maxkoshevoi/DateOnlyTimeOnly.AspNet)
- services
- .AddControllers(options => options.UseDateOnlyTimeOnlyStringConverters())
- .AddJsonOptions(options => options.UseDateOnlyTimeOnlyStringConverters());
- services.AddAndConfigureSwagger(_hostingEnvironment);
+ services.AddAndConfigureDomainServices((settings.ConnectionString, true))
+ .AddAndConfigureSwagger(_hostingEnvironment)
+ .AddControllers();
}
public void Configure(IApplicationBuilder app)
diff --git a/Domain/Configuration/AddAndConfigureDbContext.cs b/Database/Configuration/AddAndConfigureDbContext.cs
similarity index 94%
rename from Domain/Configuration/AddAndConfigureDbContext.cs
rename to Database/Configuration/AddAndConfigureDbContext.cs
index 7969e18..dc96e61 100644
--- a/Domain/Configuration/AddAndConfigureDbContext.cs
+++ b/Database/Configuration/AddAndConfigureDbContext.cs
@@ -1,9 +1,7 @@
-using AK.DbSample.Database;
-
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
-namespace AK.DbSample.Domain.Configuration;
+namespace AK.DbSample.Database.Configuration;
public static partial class ServiceCollectionExtensions
{
diff --git a/Database/DataContext.cs b/Database/DataContext.cs
index 18899b4..53672c0 100644
--- a/Database/DataContext.cs
+++ b/Database/DataContext.cs
@@ -1,5 +1,4 @@
using AK.DbSample.Database.Entities;
-using AK.DbSample.Database.Infrastructure;
using Microsoft.EntityFrameworkCore;
@@ -20,8 +19,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Date is a DateOnly property and date on database
builder.Property(x => x.Date)
- // These converters are still required in EF 7 (https://github.com/dotnet/efcore/issues/24507)
- .HasConversion();
+ .HasColumnType("date");
// Set cascade delete
builder.HasOne(p => p.Client)
diff --git a/Database/Database.csproj b/Database/Database.csproj
index 6ccf22a..4e8c319 100644
--- a/Database/Database.csproj
+++ b/Database/Database.csproj
@@ -6,8 +6,7 @@
-
-
-
+
+
diff --git a/Database/Infrastructure/DateOnlyComparer.cs b/Database/Infrastructure/DateOnlyComparer.cs
deleted file mode 100644
index 6b76fde..0000000
--- a/Database/Infrastructure/DateOnlyComparer.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using Microsoft.EntityFrameworkCore.ChangeTracking;
-
-namespace AK.DbSample.Database.Infrastructure;
-
-///
-/// Compares .
-///
-public class DateOnlyComparer : ValueComparer
-{
- ///
- /// Creates a new instance of this converter.
- ///
- public DateOnlyComparer() : base(
- (d1, d2) => d1 == d2 && d1.DayNumber == d2.DayNumber,
- d => d.GetHashCode()) {}
-}
-
-///
-/// Compares .
-///
-public class NullableDateOnlyComparer : ValueComparer
-{
- ///
- /// Creates a new instance of this converter.
- ///
- public NullableDateOnlyComparer() : base(
- (d1, d2) => d1 == d2 && d1.GetValueOrDefault().DayNumber == d2.GetValueOrDefault().DayNumber,
- d => d.GetHashCode()) {}
-}
\ No newline at end of file
diff --git a/Database/Infrastructure/DateOnlyConverter.cs b/Database/Infrastructure/DateOnlyConverter.cs
deleted file mode 100644
index 12925af..0000000
--- a/Database/Infrastructure/DateOnlyConverter.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-namespace AK.DbSample.Database.Infrastructure;
-
-///
-/// Converts to and vice versa.
-///
-public class DateOnlyConverter : ValueConverter
-{
- ///
- /// Creates a new instance of this converter.
- ///
- public DateOnlyConverter() : base(
- d => d.ToDateTime(TimeOnly.MinValue),
- d => DateOnly.FromDateTime(d)) { }
-}
-
-///
-/// Converts to and vice versa.
-///
-public class NullableDateOnlyConverter : ValueConverter
-{
- ///
- /// Creates a new instance of this converter.
- ///
- public NullableDateOnlyConverter() : base(
- d => d == null
- ? null
- : new DateTime?(d.Value.ToDateTime(TimeOnly.MinValue)),
- d => d == null
- ? null
- : new DateOnly?(DateOnly.FromDateTime(d.Value)))
- { }
-}
\ No newline at end of file
diff --git a/Database/Migrations/20220322114144_InititalCreate.cs b/Database/Migrations/20220322114144_InititalCreate.cs
index 3456329..f2f6cdd 100644
--- a/Database/Migrations/20220322114144_InititalCreate.cs
+++ b/Database/Migrations/20220322114144_InititalCreate.cs
@@ -28,7 +28,7 @@ protected override void Up(MigrationBuilder migrationBuilder)
{
Number = table.Column(type: "nvarchar(100)", nullable: false),
ClientId = table.Column(type: "bigint", nullable: false),
- Date = table.Column(type: "datetime", nullable: false),
+ Date = table.Column(type: "date", nullable: false),
Amount = table.Column(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
diff --git a/DbSample.csproj b/DbSample.csproj
deleted file mode 100644
index 27f4eb5..0000000
--- a/DbSample.csproj
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
- net6.0
- enable
- enable
- AK.DbSample.DbSample
- AK.DbSample.DbSample
-
-
-
diff --git a/Directory.Build.props b/Directory.Build.props
index 36a00cc..fe3af31 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,6 +1,6 @@
- net7.0
+ net8.0
latest
enable
strict
diff --git a/Domain.Tests/Domain.Tests.csproj b/Domain.Tests/Domain.Tests.csproj
index 008a5fc..5e66961 100644
--- a/Domain.Tests/Domain.Tests.csproj
+++ b/Domain.Tests/Domain.Tests.csproj
@@ -7,23 +7,21 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/Domain.Tests/TestDbBase.cs b/Domain.Tests/TestDbBase.cs
index a0e543b..2e41c32 100644
--- a/Domain.Tests/TestDbBase.cs
+++ b/Domain.Tests/TestDbBase.cs
@@ -1,6 +1,6 @@
using AK.DbSample.Database;
+using AK.DbSample.Database.Configuration;
using AK.DbSample.Database.Entities;
-using AK.DbSample.Domain.Configuration;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
@@ -20,21 +20,16 @@ namespace AK.DbSample.Domain.Tests;
/// Base test class with a DI container and DB connection.
/// Derive from it when need DI and DB connection
///
-public abstract class TestDbBase : TestBase, IAsyncLifetime
+public abstract class TestDbBase(ITestOutputHelper output) : TestBase, IAsyncLifetime
{
protected DataContext DataContext => Container.GetRequiredService();
- protected readonly ITestOutputHelper Output;
+ protected readonly ITestOutputHelper Output = output;
///
/// Tables that shouldn't be touched on whipping out the DB
///
- private readonly Table[] _tablesToIgnore = { Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.DefaultTableName /* "__EFMigrationsHistory" */ };
+ private readonly Table[] _tablesToIgnore = [Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.DefaultTableName /* "__EFMigrationsHistory" */];
- protected TestDbBase(ITestOutputHelper output)
- {
- Output = output;
- }
-
///
/// Configure the DI container
///
@@ -83,7 +78,7 @@ public async Task InitializeAsync()
///
/// Wipe out all data in the database
///
- protected async Task WipeOutDbAsync()
+ private async Task WipeOutDbAsync()
{
Respawner? respawn = null;
try
diff --git a/Domain/Configuration/AddAndConfigureDomainServices.cs b/Domain/Configuration/AddAndConfigureDomainServices.cs
index 58b93c9..07a3e29 100644
--- a/Domain/Configuration/AddAndConfigureDomainServices.cs
+++ b/Domain/Configuration/AddAndConfigureDomainServices.cs
@@ -1,3 +1,4 @@
+using AK.DbSample.Database.Configuration;
using AK.DbSample.Domain.Helpers;
using AK.DbSample.Domain.Services;
@@ -5,9 +6,9 @@
namespace AK.DbSample.Domain.Configuration;
-public static partial class ServiceCollectionExtensions
+public static class ServiceCollectionExtensions
{
- public static void AddAndConfigureDomainServices(this IServiceCollection services, (string? connectionString, bool registerMigrationsAssembly)? configureDatabase = null)
+ public static IServiceCollection AddAndConfigureDomainServices(this IServiceCollection services, (string? connectionString, bool registerMigrationsAssembly)? configureDatabase = null)
{
if (configureDatabase.HasValue)
services.AddAndConfigureDbContext(configureDatabase.Value.connectionString, configureDatabase.Value.registerMigrationsAssembly);
@@ -19,6 +20,6 @@ public static void AddAndConfigureDomainServices(this IServiceCollection service
&& t.IsAssignableTo() // All services
).ToList();
- services.RegisterAsImplementedInterfaces(types, ServiceLifetime.Scoped);
+ return services.RegisterAsImplementedInterfaces(types, ServiceLifetime.Scoped);
}
}
\ No newline at end of file
diff --git a/Domain/Domain.csproj b/Domain/Domain.csproj
index 6411d1a..62dcdd2 100644
--- a/Domain/Domain.csproj
+++ b/Domain/Domain.csproj
@@ -7,13 +7,13 @@
+
all
-
-
+
diff --git a/Domain/Services/BaseService.cs b/Domain/Services/BaseService.cs
index 531887a..b05b170 100644
--- a/Domain/Services/BaseService.cs
+++ b/Domain/Services/BaseService.cs
@@ -2,12 +2,7 @@
namespace AK.DbSample.Domain.Services;
-public abstract class BaseService
+public abstract class BaseService(DataContext dataContext)
{
- protected readonly DataContext DataContext;
-
- protected BaseService(DataContext dataContext)
- {
- DataContext = dataContext;
- }
+ protected readonly DataContext DataContext = dataContext;
}
\ No newline at end of file
diff --git a/Domain/Services/Client/ClientCommandService.cs b/Domain/Services/Client/ClientCommandService.cs
index 21c66f9..d00533b 100644
--- a/Domain/Services/Client/ClientCommandService.cs
+++ b/Domain/Services/Client/ClientCommandService.cs
@@ -14,10 +14,8 @@ public interface IClientCommandService
Task Delete(long id);
}
-public class ClientCommandService: BaseService, IClientCommandService
+public class ClientCommandService(DataContext dataContext) : BaseService(dataContext), IClientCommandService
{
- public ClientCommandService(DataContext dataContext) : base(dataContext) {}
-
public async Task<(long, IDomainResult)> Create(CreateUpdateClientRequest dto)
{
var nameCheckResult = await UniqueNameCheck(null, dto.Name);
diff --git a/Domain/Services/Client/ClientQueryService.cs b/Domain/Services/Client/ClientQueryService.cs
index 266ee85..c8b0ac2 100644
--- a/Domain/Services/Client/ClientQueryService.cs
+++ b/Domain/Services/Client/ClientQueryService.cs
@@ -13,10 +13,8 @@ public interface IClientQueryService
Task GetList(GetClientListRequest filter);
}
-public class ClientQueryService: BaseService, IClientQueryService
+public class ClientQueryService(DataContext dataContext) : BaseService(dataContext), IClientQueryService
{
- public ClientQueryService(DataContext dataContext) : base(dataContext) {}
-
public async Task<(GetClientByIdResponse, IDomainResult)> GetById(long clientId)
{
var client = await DataContext.Clients
diff --git a/Domain/Services/Client/DTOs/ClientQueryDtos.cs b/Domain/Services/Client/DTOs/ClientQueryDtos.cs
index 48fff19..3e8e06f 100644
--- a/Domain/Services/Client/DTOs/ClientQueryDtos.cs
+++ b/Domain/Services/Client/DTOs/ClientQueryDtos.cs
@@ -1,3 +1,4 @@
+// ReSharper disable NotAccessedPositionalProperty.Global
namespace AK.DbSample.Domain.Services.Client.DTOs;
public record GetClientListRequest(string? Name = null);
diff --git a/Domain/Services/Invoice/DTOs/InvoiceQueryDtos.cs b/Domain/Services/Invoice/DTOs/InvoiceQueryDtos.cs
index 5e5d623..3b2d9b6 100644
--- a/Domain/Services/Invoice/DTOs/InvoiceQueryDtos.cs
+++ b/Domain/Services/Invoice/DTOs/InvoiceQueryDtos.cs
@@ -1,3 +1,4 @@
+// ReSharper disable NotAccessedPositionalProperty.Global
namespace AK.DbSample.Domain.Services.Invoice.DTOs;
public record GetInvoiceListRequest(long? ClientId = null);
diff --git a/Domain/Services/Invoice/InvoiceCommandService.cs b/Domain/Services/Invoice/InvoiceCommandService.cs
index 447d4bc..78eae73 100644
--- a/Domain/Services/Invoice/InvoiceCommandService.cs
+++ b/Domain/Services/Invoice/InvoiceCommandService.cs
@@ -14,10 +14,8 @@ public interface IInvoiceCommandService
Task Delete(string number);
}
-public class InvoiceCommandService: BaseService, IInvoiceCommandService
+public class InvoiceCommandService(DataContext dataContext) : BaseService(dataContext), IInvoiceCommandService
{
- public InvoiceCommandService(DataContext dataContext) : base(dataContext) {}
-
public async Task<(string, IDomainResult)> Create(CreateInvoiceRequest dto)
{
var numberCheckResult = await UniqueNumberCheck(dto.Number, true);
diff --git a/Domain/Services/Invoice/InvoiceQueryService.cs b/Domain/Services/Invoice/InvoiceQueryService.cs
index 0b28d62..2deb5fe 100644
--- a/Domain/Services/Invoice/InvoiceQueryService.cs
+++ b/Domain/Services/Invoice/InvoiceQueryService.cs
@@ -13,10 +13,8 @@ public interface IInvoiceQueryService
Task GetList(GetInvoiceListRequest filter);
}
-public class InvoiceQueryService: BaseService, IInvoiceQueryService
+public class InvoiceQueryService(DataContext dataContext) : BaseService(dataContext), IInvoiceQueryService
{
- public InvoiceQueryService(DataContext dataContext) : base(dataContext) {}
-
public async Task<(GetInvoiceByNumberResponse, IDomainResult)> GetByNumber(string number)
{
var invoice = await DataContext.Invoices
diff --git a/README.md b/README.md
index 91b0306..1317416 100644
--- a/README.md
+++ b/README.md
@@ -25,8 +25,8 @@ See "[Pain & Gain of automated tests against SQL (MS SQL or PostgreSQL)](https:/
### Technologies
- Main project:
- - [.NET 7](https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-7);
- - [Entity Framework Core 7](https://docs.microsoft.com/en-us/ef/core/) and [dotnet-ef](https://docs.microsoft.com/en-us/ef/core/cli/dotnet) CLI.
+ - [.NET 8](https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8);
+ - [Entity Framework Core 8](https://docs.microsoft.com/en-us/ef/core/) and [dotnet-ef](https://docs.microsoft.com/en-us/ef/core/cli/dotnet) CLI.
- Test project:
- [xUnit](https://xunit.net/) + [Respawn](https://github.com/jbogard/Respawn);
- [Docker](https://www.docker.com/) + [SQL Server image](https://hub.docker.com/_/microsoft-mssql-server).
@@ -34,7 +34,7 @@ See "[Pain & Gain of automated tests against SQL (MS SQL or PostgreSQL)](https:/
## Getting Started (locally)
Firstly, check out this Git repo and install dependencies:
- - [.NET SDK](https://dotnet.microsoft.com/download) v7.x;
+ - [.NET SDK](https://dotnet.microsoft.com/download) v8.x;
- [dotnet-ef](https://docs.microsoft.com/en-us/ef/core/cli/dotnet) CLI;
- [Docker](https://www.docker.com/).
diff --git a/devops/start_docker_sql_server_with_new_db.sh b/devops/start_docker_sql_server_with_new_db.sh
index b4344fb..ee534f7 100755
--- a/devops/start_docker_sql_server_with_new_db.sh
+++ b/devops/start_docker_sql_server_with_new_db.sh
@@ -4,7 +4,7 @@ saPassword="Secret_Passw0rd"
dbName="SampleDb"
if [ -z "$1" ]; then
- echo "Provide path to a SQL script for creating DB schema"
+ echo "ERROR! No path to a SQL script for creating DB schema. Provide as a parameter"
exit 1
fi
createDbSqlScript="$1"