Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace EvolutionaryArchitecture.Fitnet.Contracts.Data.Database;

using System.ComponentModel.DataAnnotations;

internal sealed class ContractsPersistenceOptions
{
public const string SectionName = "ConnectionStrings";

Comment on lines +5 to +8
Copy link

Copilot AI Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The section name "ConnectionStrings" is duplicated across all persistence options classes. Consider creating a shared constant or base class to avoid code duplication and ensure consistency.

Suggested change
internal sealed class ContractsPersistenceOptions
{
public const string SectionName = "ConnectionStrings";
internal static class PersistenceOptionsConstants
{
public const string SectionName = "ConnectionStrings";
}
internal sealed class ContractsPersistenceOptions
{
// Use PersistenceOptionsConstants.SectionName where needed

Copilot uses AI. Check for mistakes.
[Required] public string Contracts { get; init; } = string.Empty;
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
namespace EvolutionaryArchitecture.Fitnet.Contracts.Data.Database;

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;

internal static class DatabaseModule
{
private const string ConnectionStringName = "Contracts";

internal static IServiceCollection AddDatabase(this IServiceCollection services, IConfiguration configuration)
{
var connectionString = configuration.GetConnectionString(ConnectionStringName);
services.AddDbContext<ContractsPersistence>(options => options.UseNpgsql(connectionString));
services.Configure<ContractsPersistenceOptions>(
configuration.GetSection(ContractsPersistenceOptions.SectionName));
services.AddOptionsWithValidateOnStart<ContractsPersistenceOptions>();

services.AddDbContext<ContractsPersistence>((serviceProvider, options) =>
{
var persistenceOptions = serviceProvider.GetRequiredService<IOptions<ContractsPersistenceOptions>>();
var connectionString = persistenceOptions.Value.Contracts;
options.UseNpgsql(connectionString);
});

return services;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
namespace EvolutionaryArchitecture.Fitnet.Offers.Data.Database;

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;

internal static class DatabaseModule
{
private const string ConnectionStringName = "Offers";

internal static IServiceCollection AddDatabase(this IServiceCollection services, IConfiguration configuration)
{
var connectionString = configuration.GetConnectionString(ConnectionStringName);
services.AddDbContext<OffersPersistence>(options => options.UseNpgsql(connectionString));
services.Configure<OffersPersistenceOptions>(configuration.GetSection(OffersPersistenceOptions.SectionName));
services.AddOptionsWithValidateOnStart<OffersPersistenceOptions>();

services.AddDbContext<OffersPersistence>((serviceProvider, options) =>
{
var persistenceOptions = serviceProvider.GetRequiredService<IOptions<OffersPersistenceOptions>>();
var connectionString = persistenceOptions.Value.Offers;
options.UseNpgsql(connectionString);
});

return services;
}
Expand All @@ -20,4 +26,4 @@ internal static IApplicationBuilder UseDatabase(this IApplicationBuilder applica

return applicationBuilder;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace EvolutionaryArchitecture.Fitnet.Offers.Data.Database;

using System.ComponentModel.DataAnnotations;

internal sealed class OffersPersistenceOptions
{
public const string SectionName = "ConnectionStrings";

Comment on lines +5 to +8
Copy link

Copilot AI Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The section name "ConnectionStrings" is duplicated across all persistence options classes. Consider creating a shared constant or base class to avoid code duplication and ensure consistency.

Suggested change
internal sealed class OffersPersistenceOptions
{
public const string SectionName = "ConnectionStrings";
internal static class PersistenceOptionSectionNames
{
public const string ConnectionStrings = "ConnectionStrings";
}
internal sealed class OffersPersistenceOptions
{
// Use PersistenceOptionSectionNames.ConnectionStrings where needed

Copilot uses AI. Check for mistakes.
[Required] public string Offers { get; init; } = string.Empty;
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
namespace EvolutionaryArchitecture.Fitnet.Passes.Data.Database;

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;

internal static class DatabaseModule
{
private const string ConnectionStringName = "Passes";

internal static IServiceCollection AddDatabase(this IServiceCollection services, IConfiguration configuration)
{
var connectionString = configuration.GetConnectionString(ConnectionStringName);
services.AddDbContext<PassesPersistence>(options => options.UseNpgsql(connectionString));
services.Configure<PassesPersistenceOptions>(configuration.GetSection(PassesPersistenceOptions.SectionName));
services.AddOptionsWithValidateOnStart<PassesPersistenceOptions>();

services.AddDbContext<PassesPersistence>((serviceProvider, options) =>
{
var persistenceOptions = serviceProvider.GetRequiredService<IOptions<PassesPersistenceOptions>>();
var connectionString = persistenceOptions.Value.Passes;
options.UseNpgsql(connectionString);
});

return services;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace EvolutionaryArchitecture.Fitnet.Passes.Data.Database;

using System.ComponentModel.DataAnnotations;

internal sealed class PassesPersistenceOptions
{
public const string SectionName = "ConnectionStrings";

Comment on lines +5 to +8
Copy link

Copilot AI Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The section name "ConnectionStrings" is duplicated across all persistence options classes. Consider creating a shared constant or base class to avoid code duplication and ensure consistency.

Suggested change
internal sealed class PassesPersistenceOptions
{
public const string SectionName = "ConnectionStrings";
internal static class PersistenceOptionsConstants
{
public const string SectionName = "ConnectionStrings";
}
internal sealed class PassesPersistenceOptions
{
public const string SectionName = PersistenceOptionsConstants.SectionName;

Copilot uses AI. Check for mistakes.
[Required] public string Passes { get; init; } = string.Empty;
}
3 changes: 2 additions & 1 deletion Chapter-1-initial-architecture/Src/Fitnet/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
builder.Services.AddRequestsValidations();
builder.Services.AddClock();

// Add modules - each module registers its own options with validation
builder.Services.AddPasses(builder.Configuration);
builder.Services.AddContracts(builder.Configuration);
builder.Services.AddOffers(builder.Configuration);
builder.Services.AddReports();
builder.Services.AddReports(builder.Configuration);

var app = builder.Build();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace EvolutionaryArchitecture.Fitnet.Reports.DataAccess;

internal static class DataAccessModule
{
internal static IServiceCollection AddDataAccess(this IServiceCollection services, IConfiguration configuration)
{
services.Configure<ReportsPersistenceOptions>(configuration.GetSection(ReportsPersistenceOptions.SectionName));
services.AddOptionsWithValidateOnStart<ReportsPersistenceOptions>();

services.AddScoped<IDatabaseConnectionFactory, DatabaseConnectionFactory>();

return services;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
namespace EvolutionaryArchitecture.Fitnet.Reports.DataAccess;

using System.Data;
using Microsoft.Extensions.Options;
using Npgsql;

internal sealed class DatabaseConnectionFactory(IConfiguration configuration) : IDatabaseConnectionFactory
internal sealed class DatabaseConnectionFactory(IOptions<ReportsPersistenceOptions> persistenceOptions)
: IDatabaseConnectionFactory
{
private NpgsqlConnection? _connection;

Expand All @@ -14,8 +16,7 @@ public IDbConnection Create()
return _connection;
}

_connection =
new NpgsqlConnection(configuration.GetConnectionString("Reports"));
_connection = new NpgsqlConnection(persistenceOptions.Value.Reports);
_connection.Open();

return _connection;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace EvolutionaryArchitecture.Fitnet.Reports.DataAccess;

using System.ComponentModel.DataAnnotations;

internal sealed class ReportsPersistenceOptions
{
public const string SectionName = "ConnectionStrings";

Comment on lines +5 to +8
Copy link

Copilot AI Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The section name "ConnectionStrings" is duplicated across all persistence options classes. Consider creating a shared constant or base class to avoid code duplication and ensure consistency.

Suggested change
internal sealed class ReportsPersistenceOptions
{
public const string SectionName = "ConnectionStrings";
internal static class PersistenceOptionsConstants
{
public const string SectionName = "ConnectionStrings";
}
internal sealed class ReportsPersistenceOptions
{
public const string SectionName = PersistenceOptionsConstants.SectionName;

Copilot uses AI. Check for mistakes.
[Required] public string Reports { get; init; } = string.Empty;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ namespace EvolutionaryArchitecture.Fitnet.Reports;

internal static class ReportsModule
{
internal static IServiceCollection AddReports(this IServiceCollection services)
internal static IServiceCollection AddReports(this IServiceCollection services, IConfiguration configuration)
{
services.AddDataAccess();
services.AddDataAccess(configuration);
services.AddNewPassesRegistrationsPerMonthReport();

return services;
Expand Down