Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
@@ -1,10 +1,9 @@
namespace DigitalLearningSolutions.Data.DataServices
{
using Dapper;
using DigitalLearningSolutions.Data.Factories;
using DigitalLearningSolutions.Data.Models.PlatformReports;
using DigitalLearningSolutions.Data.Models.SelfAssessments;
using DigitalLearningSolutions.Data.Models.TrackingSystem;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Data;
Expand Down Expand Up @@ -37,9 +36,9 @@ IEnumerable<ActivityLog> GetFilteredCourseActivity(
);
DateTime? GetStartOfCourseActivity();
}
public class PlatformReportsDataService : IPlatformReportsDataService
public class PlatformReportsDataService(IReadOnlyDbConnectionFactory factory) : IPlatformReportsDataService
{
private readonly IDbConnection connection;
private readonly IDbConnection connection = factory.CreateConnection();
private readonly string selectSelfAssessmentActivity = @"SELECT Cast(al.ActivityDate As Date) As ActivityDate, SUM(CAST(al.Enrolled AS Int)) AS Enrolled, SUM(CAST((al.Submitted | al.SignedOff) AS Int)) AS Completed
FROM ReportSelfAssessmentActivityLog AS al WITH (NOLOCK) INNER JOIN
Centres AS ce WITH (NOLOCK) ON al.CentreID = ce.CentreID INNER JOIN
Expand All @@ -60,10 +59,6 @@ private string GetSelfAssessmentWhereClause(bool supervised)
return supervised ? " (sa.SupervisorResultsReview = 1 OR SupervisorSelfAssessmentReview = 1)" : " (sa.SupervisorResultsReview = 0 AND SupervisorSelfAssessmentReview = 0)";
}

public PlatformReportsDataService(IDbConnection connection)
{
this.connection = connection;
}
public PlatformUsageSummary GetPlatformUsageSummary()
{
return connection.QueryFirstOrDefault<PlatformUsageSummary>(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace DigitalLearningSolutions.Data.DataServices.SelfAssessmentDataService
{
using Dapper;
using DigitalLearningSolutions.Data.Factories;
using DigitalLearningSolutions.Data.Models.SelfAssessments.Export;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
Expand All @@ -11,16 +12,10 @@ public interface IDCSAReportDataService
IEnumerable<DCSADelegateCompletionStatus> GetDelegateCompletionStatusForCentre(int centreId);
IEnumerable<DCSAOutcomeSummary> GetOutcomeSummaryForCentre(int centreId);
}
public partial class DCSAReportDataService : IDCSAReportDataService
public partial class DCSAReportDataService(IReadOnlyDbConnectionFactory factory, ILogger<SelfAssessmentDataService> logger) : IDCSAReportDataService
{
private readonly IDbConnection connection;
private readonly ILogger<SelfAssessmentDataService> logger;

public DCSAReportDataService(IDbConnection connection, ILogger<SelfAssessmentDataService> logger)
{
this.connection = connection;
this.logger = logger;
}
private readonly IDbConnection connection = factory.CreateConnection();
private readonly ILogger<SelfAssessmentDataService> logger = logger;

public IEnumerable<DCSADelegateCompletionStatus> GetDelegateCompletionStatusForCentre(int centreId)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,17 @@
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System.Data;
using ClosedXML.Excel;
using DigitalLearningSolutions.Data.Factories;

public interface ISelfAssessmentReportDataService
{
IEnumerable<SelfAssessmentSelect> GetSelfAssessmentsForReportList(int centreId, int? categoryId);
IEnumerable<SelfAssessmentReportData> GetSelfAssessmentReportDataForCentre(int centreId, int selfAssessmentId);
}
public partial class SelfAssessmentReportDataService : ISelfAssessmentReportDataService
public partial class SelfAssessmentReportDataService(IReadOnlyDbConnectionFactory factory, ILogger<SelfAssessmentReportDataService> logger) : ISelfAssessmentReportDataService
{
private readonly IDbConnection connection;
private readonly ILogger<SelfAssessmentReportDataService> logger;

public SelfAssessmentReportDataService(IDbConnection connection, ILogger<SelfAssessmentReportDataService> logger)
{
this.connection = connection;
this.logger = logger;
}
private readonly IDbConnection connection = factory.CreateConnection();
private readonly ILogger<SelfAssessmentReportDataService> logger = logger;

public IEnumerable<SelfAssessmentSelect> GetSelfAssessmentsForReportList(int centreId, int? categoryId)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<PackageReference Include="Freshdesk.Api" Version="0.17.2" />
<PackageReference Include="FuzzySharp" Version="2.0.2" />
<PackageReference Include="MailKit" Version="4.3.0" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.1" />
<PackageReference Include="Microsoft.FeatureManagement.AspNetCore" Version="2.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
<PackageReference Include="System.Drawing.Common" Version="9.0.1" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace DigitalLearningSolutions.Data.Factories
{
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Configuration;
using System;
using System.Data;
public interface IReadOnlyDbConnectionFactory
{
IDbConnection CreateConnection();
}
public class ReadOnlyDbConnectionFactory : IReadOnlyDbConnectionFactory
{
private const string ReadOnlyConnectionName = "ReadOnlyConnection";
private readonly string connectionString;

public ReadOnlyDbConnectionFactory(IConfiguration config)
{
// Ensure the connection string is not null to avoid CS8601
connectionString = config.GetConnectionString(ReadOnlyConnectionName)
?? throw new InvalidOperationException($"Connection string '{ReadOnlyConnectionName}' is not configured.");
}

public IDbConnection CreateConnection()
{
// Ensure the connection is not enlisted in the trasaction scope to avoid distributed transaction errors:
return new SqlConnection(connectionString + ";Enlist=false");
}
}
}
1 change: 1 addition & 0 deletions DigitalLearningSolutions.Web/Helpers/ConfigHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
public static class ConfigHelper
{
public const string DefaultConnectionStringName = "DefaultConnection";
public const string ReadOnlyConnectionStringName = "ReadOnlyConnection";
public const string UnitTestConnectionStringName = "UnitTestConnection";

public static IConfigurationRoot GetAppConfig()
Expand Down
27 changes: 14 additions & 13 deletions DigitalLearningSolutions.Web/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
namespace DigitalLearningSolutions.Web
{
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Transactions;
using System.Web;
using AspNetCoreRateLimit;
using DigitalLearningSolutions.Data.ApiClients;
using DigitalLearningSolutions.Data.DataServices;
Expand Down Expand Up @@ -39,19 +31,27 @@ namespace DigitalLearningSolutions.Web
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.FeatureManagement;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.AspNetCore.Identity;
using Serilog;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Transactions;
using System.Web;
using static DigitalLearningSolutions.Data.DataServices.ICentreApplicationsDataService;
using static DigitalLearningSolutions.Web.Services.ICentreApplicationsService;
using static DigitalLearningSolutions.Web.Services.ICentreSelfAssessmentsService;
using System;
using Serilog;

public class Startup
{
Expand All @@ -65,7 +65,6 @@ public Startup(IConfiguration config, IHostEnvironment env)
this.config = config;
this.env = env;
}

public void ConfigureServices(IServiceCollection services)
{
ConfigureIpRateLimiting(services);
Expand Down Expand Up @@ -194,6 +193,8 @@ public void ConfigureServices(IServiceCollection services)

// Register database connection for Dapper.
services.AddScoped<IDbConnection>(_ => new SqlConnection(defaultConnectionString));
// Register factory for read-only replica connections
services.AddScoped<IReadOnlyDbConnectionFactory, ReadOnlyDbConnectionFactory>();
Dapper.SqlMapper.Settings.CommandTimeout = 60;

MultiPageFormService.InitConnection(new SqlConnection(defaultConnectionString));
Expand Down Expand Up @@ -510,6 +511,7 @@ private static void RegisterDataServices(IServiceCollection services)
services.AddScoped<IRoleProfileDataService, RoleProfileDataService>();
services.AddScoped<ISectionContentDataService, SectionContentDataService>();
services.AddScoped<ISelfAssessmentDataService, SelfAssessmentDataService>();
services.AddScoped<ISelfAssessmentReportDataService, SelfAssessmentReportDataService>();
services.AddScoped<ISessionDataService, SessionDataService>();
services.AddScoped<ISupervisorDataService, SupervisorDataService>();
services.AddScoped<ISupervisorDelegateDataService, SupervisorDelegateDataService>();
Expand All @@ -525,7 +527,6 @@ private static void RegisterDataServices(IServiceCollection services)
services.AddScoped<ICacheService, CacheService>();
services.AddScoped<RedisCacheOptions, RedisCacheOptions>();
services.AddScoped<IMultiPageFormService, MultiPageFormService>();
services.AddScoped<ISelfAssessmentReportDataService, SelfAssessmentReportDataService>();
services.AddScoped<IUserFeedbackDataService, UserFeedbackDataService>();
services.AddScoped<IPlatformReportsDataService, PlatformReportsDataService>();
services.AddScoped<IContractTypesDataService, ContractTypesDataService>();
Expand Down
1 change: 1 addition & 0 deletions DigitalLearningSolutions.Web/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "Data Source=localhost;Initial Catalog=mbdbx101_uar;Integrated Security=True;encrypt=false;TrustServerCertificate=true;",
"ReadOnlyConnection": "Data Source=localhost;Initial Catalog=mbdbx101_uar;Integrated Security=True;encrypt=false;TrustServerCertificate=true;",
"UnitTestConnection": "Data Source=localhost;Initial Catalog=mbdbx101_uar_test;Integrated Security=True;encrypt=false;TrustServerCertificate=true;"
},
"CurrentSystemBaseUrl": "https://www.dls.nhs.uk",
Expand Down
Loading