|
- using System.Data.Common;
- using System.Data.OleDb;
- using System.Runtime.Versioning;
- using Campaign_Tracker.Server.LegacyData.Models;
-
- namespace Campaign_Tracker.Server.LegacyData;
-
- /// <summary>
- /// Read-only OleDb implementation for legacy Access-derived data.
- /// All SQL is parameterized and validated as SELECT-only before execution.
- /// </summary>
- [SupportedOSPlatform("windows")]
- public sealed class OleDbLegacyDataAccess : ILegacyDataAccess
- {
- private readonly string _connectionString;
-
- public OleDbLegacyDataAccess(string connectionString)
- {
- if (string.IsNullOrWhiteSpace(connectionString))
- {
- throw new ArgumentException("Legacy database connection string is required.", nameof(connectionString));
- }
-
- _connectionString = connectionString;
- }
-
- public async Task<LegacyJurisdiction?> GetJurisdictionAsync(
- string jCode,
- CancellationToken cancellationToken = default)
- {
- const string sql = """
- SELECT JCode, Name, Mailing_Address, CSZ, IMB, IMB_Digits
- FROM Jurisdiction
- WHERE Trim(JCode) = ?
- """;
-
- var results = await QueryAsync(sql, [jCode.Trim()], MapJurisdiction, cancellationToken);
- return results.FirstOrDefault();
- }
-
- public Task<IReadOnlyList<LegacyJurisdiction>> GetAllJurisdictionsAsync(
- CancellationToken cancellationToken = default)
- {
- const string sql = """
- SELECT JCode, Name, Mailing_Address, CSZ, IMB, IMB_Digits
- FROM Jurisdiction
- ORDER BY JCode
- """;
-
- return QueryAsync(sql, [], MapJurisdiction, cancellationToken);
- }
-
- public async Task<LegacyContact?> GetContactByIdAsync(
- int id,
- CancellationToken cancellationToken = default)
- {
- const string sql = """
- SELECT ID, JURISCODE, ContactName, Title, Email, Phone1, Phone2,
- MailingAddress, MailingAddress2, MailingAddress3,
- BusinessAddress, BusinessAddress2, BusinessAddress3,
- TownshipName, TownshipNum
- FROM Contacts
- WHERE ID = ?
- """;
-
- var results = await QueryAsync(sql, [id], MapContact, cancellationToken);
- return results.FirstOrDefault();
- }
-
- public Task<IReadOnlyList<LegacyContact>> GetContactsByJurisdictionAsync(
- string jCode,
- CancellationToken cancellationToken = default)
- {
- const string sql = """
- SELECT ID, JURISCODE, ContactName, Title, Email, Phone1, Phone2,
- MailingAddress, MailingAddress2, MailingAddress3,
- BusinessAddress, BusinessAddress2, BusinessAddress3,
- TownshipName, TownshipNum
- FROM Contacts
- WHERE Trim(JURISCODE) = ?
- ORDER BY ID
- """;
-
- return QueryAsync(sql, [jCode.Trim()], MapContact, cancellationToken);
- }
-
- public async Task<LegacyKit?> GetKitByIdAsync(
- int id,
- CancellationToken cancellationToken = default)
- {
- const string sql = """
- SELECT ID, Jcode, JobNumber, JobType, Status, Filename, Cass, InkJetJob,
- CreatedOn, ExportedToSnailWorks, LabelsPrinted, OfficeCopiesAmount,
- InboundStid, OutboundStid
- FROM Kit
- WHERE ID = ?
- """;
-
- var results = await QueryAsync(sql, [id], MapKit, cancellationToken);
- return results.FirstOrDefault();
- }
-
- public Task<IReadOnlyList<LegacyKit>> GetKitsByJurisdictionAsync(
- string jCode,
- CancellationToken cancellationToken = default)
- {
- const string sql = """
- SELECT ID, Jcode, JobNumber, JobType, Status, Filename, Cass, InkJetJob,
- CreatedOn, ExportedToSnailWorks, LabelsPrinted, OfficeCopiesAmount,
- InboundStid, OutboundStid
- FROM Kit
- WHERE Trim(Jcode) = ?
- ORDER BY ID
- """;
-
- return QueryAsync(sql, [jCode.Trim()], MapKit, cancellationToken);
- }
-
- public Task<IReadOnlyList<LegacyKitLabel>> GetKitLabelsByKitAsync(
- int kitId,
- CancellationToken cancellationToken = default)
- {
- const string sql = """
- SELECT ID, KitID, InBoundImb, InBoundImbDigits, InBoundSerial,
- OutboundImb, OutboundImbDigits, OutboundSerial, SetNumber
- FROM KitLabels
- WHERE KitID = ?
- ORDER BY ID
- """;
-
- return QueryAsync(sql, [kitId], MapKitLabel, cancellationToken);
- }
-
- private async Task<IReadOnlyList<T>> QueryAsync<T>(
- string sql,
- IReadOnlyList<object> parameters,
- Func<DbDataReader, T> map,
- CancellationToken cancellationToken)
- {
- ReadOnlyCommandGuard.Validate(sql);
-
- try
- {
- await using var connection = new OleDbConnection(_connectionString);
- await connection.OpenAsync(cancellationToken);
-
- await using var command = connection.CreateCommand();
- command.CommandText = sql;
- foreach (var parameter in parameters)
- {
- command.Parameters.AddWithValue(string.Empty, parameter);
- }
-
- var results = new List<T>();
- await using var reader = await command.ExecuteReaderAsync(cancellationToken);
- while (await reader.ReadAsync(cancellationToken))
- {
- results.Add(map(reader));
- }
-
- return results;
- }
- catch (LegacyDataAccessException)
- {
- throw;
- }
- catch (Exception ex)
- {
- throw new LegacyDataAccessException("Legacy read operation failed.", ex);
- }
- }
-
- private static LegacyJurisdiction MapJurisdiction(DbDataReader reader) =>
- new(
- GetRequiredString(reader, "JCode"),
- GetString(reader, "Name"),
- GetString(reader, "Mailing_Address"),
- GetString(reader, "CSZ"),
- GetString(reader, "IMB"),
- GetString(reader, "IMB_Digits"));
-
- private static LegacyContact MapContact(DbDataReader reader) =>
- new(
- GetRequiredInt(reader, "ID"),
- GetRequiredString(reader, "JURISCODE"),
- GetString(reader, "ContactName"),
- GetString(reader, "Title"),
- GetString(reader, "Email"),
- GetString(reader, "Phone1"),
- GetString(reader, "Phone2"),
- GetString(reader, "MailingAddress"),
- GetString(reader, "MailingAddress2"),
- GetString(reader, "MailingAddress3"),
- GetString(reader, "BusinessAddress"),
- GetString(reader, "BusinessAddress2"),
- GetString(reader, "BusinessAddress3"),
- GetString(reader, "TownshipName"),
- GetString(reader, "TownshipNum"));
-
- private static LegacyKit MapKit(DbDataReader reader) =>
- new(
- GetRequiredInt(reader, "ID"),
- GetRequiredString(reader, "Jcode"),
- GetString(reader, "JobNumber"),
- GetString(reader, "JobType"),
- GetString(reader, "Status"),
- GetString(reader, "Filename"),
- GetBool(reader, "Cass"),
- GetBool(reader, "InkJetJob"),
- GetDateTime(reader, "CreatedOn"),
- GetDateTime(reader, "ExportedToSnailWorks"),
- GetDateTime(reader, "LabelsPrinted"),
- GetInt(reader, "OfficeCopiesAmount"),
- GetString(reader, "InboundStid"),
- GetString(reader, "OutboundStid"));
-
- private static LegacyKitLabel MapKitLabel(DbDataReader reader) =>
- new(
- GetRequiredInt(reader, "ID"),
- GetRequiredInt(reader, "KitID"),
- GetString(reader, "InBoundImb"),
- GetString(reader, "InBoundImbDigits"),
- GetString(reader, "InBoundSerial"),
- GetString(reader, "OutboundImb"),
- GetString(reader, "OutboundImbDigits"),
- GetString(reader, "OutboundSerial"),
- GetDouble(reader, "SetNumber"));
-
- private static string GetRequiredString(DbDataReader reader, string name)
- {
- var value = GetString(reader, name)?.Trim();
- return string.IsNullOrWhiteSpace(value)
- ? throw new LegacyDataAccessException($"Required legacy join key {name} was null or empty.")
- : value;
- }
-
- private static int GetRequiredInt(DbDataReader reader, string name) =>
- GetInt(reader, name)
- ?? throw new LegacyDataAccessException($"Required legacy join key {name} was null.");
-
- private static string? GetString(DbDataReader reader, string name)
- {
- var value = GetValue(reader, name);
- return value is null ? null : Convert.ToString(value);
- }
-
- private static int? GetInt(DbDataReader reader, string name)
- {
- var value = GetValue(reader, name);
- return value is null ? null : Convert.ToInt32(value);
- }
-
- private static double? GetDouble(DbDataReader reader, string name)
- {
- var value = GetValue(reader, name);
- return value is null ? null : Convert.ToDouble(value);
- }
-
- private static bool GetBool(DbDataReader reader, string name)
- {
- var value = GetValue(reader, name);
- return value is not null && Convert.ToBoolean(value);
- }
-
- private static DateTime? GetDateTime(DbDataReader reader, string name)
- {
- var value = GetValue(reader, name);
- return value is null ? null : Convert.ToDateTime(value);
- }
-
- private static object? GetValue(DbDataReader reader, string name)
- {
- var ordinal = reader.GetOrdinal(name);
- return reader.IsDBNull(ordinal) ? null : reader.GetValue(ordinal);
- }
- }
|