Files
jdescopingtool/NEW/src/JdeScoping.DataAccess/Repositories/LotFinderRepository.Lookups.cs
T
Joseph Doherty 645ef46f35 refactor(data-access): replace TVP lookups with STRING_SPLIT and OPENJSON
Remove dependency on deleted SQL Server Table-Valued Parameter types
by refactoring lookup methods to use built-in SQL Server functions:

- Simple single-value lookups (Items, WorkOrders, WorkCenters,
  ProfitCenters, Users) now use STRING_SPLIT with comma-separated
  strings from C#
- Complex multi-column lookup (Lots with LotNumber + ItemNumber)
  now uses OPENJSON with JSON string from C#

This eliminates the need for TVP type definitions (scripts 033-039)
while maintaining equivalent functionality.
2026-01-06 15:34:39 -05:00

269 lines
9.2 KiB
C#

using Dapper;
using JdeScoping.Core.Models;
using JdeScoping.Core.Models.Inventory;
using JdeScoping.Core.Models.Organization;
using JdeScoping.Core.Models.WorkOrders;
using JdeScoping.Core.ViewModels;
using JdeScoping.DataAccess.Queries;
namespace JdeScoping.DataAccess.Repositories;
/// <summary>
/// Reference data lookup operations for LotFinder repository.
/// </summary>
public partial class LotFinderRepository
{
/// <inheritdoc/>
public async Task<List<Item>> SearchItemsAsync(string filter, CancellationToken ct = default)
{
const string operation = nameof(SearchItemsAsync);
try
{
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<Item>(
LotFinderQueries.SqlSearchItems,
new { filter },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_SEARCH_ITEMS");
throw;
}
}
/// <inheritdoc/>
public async Task<List<Item>> LookupItemsAsync(List<string> itemNumbers, CancellationToken ct = default)
{
const string operation = nameof(LookupItemsAsync);
try
{
var itemNumbersCsv = string.Join(",", itemNumbers);
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<Item>(
LotFinderQueries.SqlLookupItems,
new { itemNumbers = itemNumbersCsv },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_LOOKUP_ITEMS");
throw;
}
}
/// <inheritdoc/>
public async Task<List<WorkOrder>> LookupWorkordersAsync(List<long> workorderNumbers, CancellationToken ct = default)
{
const string operation = nameof(LookupWorkordersAsync);
try
{
var workOrderNumbersCsv = string.Join(",", workorderNumbers);
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<WorkOrder>(
LotFinderQueries.SqlLookupWorkorders,
new { workOrderNumbers = workOrderNumbersCsv },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_LOOKUP_WORKORDERS");
throw;
}
}
/// <inheritdoc/>
public async Task<List<WorkCenter>> SearchWorkCentersAsync(string filter, CancellationToken ct = default)
{
const string operation = nameof(SearchWorkCentersAsync);
try
{
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<WorkCenter>(
LotFinderQueries.SqlSearchWorkCenters,
new { filter },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_SEARCH_WORK_CENTERS");
throw;
}
}
/// <inheritdoc/>
public async Task<List<WorkCenter>> LookupWorkCentersAsync(List<string> codes, CancellationToken ct = default)
{
const string operation = nameof(LookupWorkCentersAsync);
try
{
var workCenterCodesCsv = string.Join(",", codes);
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<WorkCenter>(
LotFinderQueries.SqlLookupWorkCenters,
new { workCenterCodes = workCenterCodesCsv },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_LOOKUP_WORK_CENTERS");
throw;
}
}
/// <inheritdoc/>
public async Task<List<ProfitCenter>> SearchProfitCentersAsync(string filter, CancellationToken ct = default)
{
const string operation = nameof(SearchProfitCentersAsync);
try
{
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<ProfitCenter>(
LotFinderQueries.SqlSearchProfitCenters,
new { filter },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_SEARCH_PROFIT_CENTERS");
throw;
}
}
/// <inheritdoc/>
public async Task<List<ProfitCenter>> LookupProfitCentersAsync(List<string> codes, CancellationToken ct = default)
{
const string operation = nameof(LookupProfitCentersAsync);
try
{
var profitCenterCodesCsv = string.Join(",", codes);
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<ProfitCenter>(
LotFinderQueries.SqlLookupProfitCenters,
new { profitCenterCodes = profitCenterCodesCsv },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_LOOKUP_PROFIT_CENTERS");
throw;
}
}
/// <inheritdoc/>
public async Task<List<JdeUser>> SearchUsersAsync(string filter, CancellationToken ct = default)
{
const string operation = nameof(SearchUsersAsync);
try
{
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<JdeUser>(
LotFinderQueries.SqlSearchUsers,
new { filter },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_SEARCH_USERS");
throw;
}
}
/// <inheritdoc/>
public async Task<List<JdeUser>> LookupUsersAsync(List<string> userIds, CancellationToken ct = default)
{
const string operation = nameof(LookupUsersAsync);
try
{
var userIdsCsv = string.Join(",", userIds);
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<JdeUser>(
LotFinderQueries.SqlLookupUsers,
new { userIds = userIdsCsv },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_LOOKUP_USERS");
throw;
}
}
/// <inheritdoc/>
public async Task<List<Lot>> LookupLotsAsync(List<LotViewModel> lots, CancellationToken ct = default)
{
const string operation = nameof(LookupLotsAsync);
try
{
var lotsJson = System.Text.Json.JsonSerializer.Serialize(
lots.Select(l => new { l.LotNumber, l.ItemNumber }));
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<Lot>(
LotFinderQueries.SqlLookupLots,
new { lotsJson },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_LOOKUP_LOTS");
throw;
}
}
}