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.
This commit is contained in:
Joseph Doherty
2026-01-06 15:34:39 -05:00
parent c6aeb20d9c
commit 645ef46f35
2 changed files with 29 additions and 56 deletions
@@ -1,4 +1,3 @@
using System.Data;
using Dapper;
using JdeScoping.Core.Models;
using JdeScoping.Core.Models.Inventory;
@@ -44,17 +43,12 @@ public partial class LotFinderRepository
const string operation = nameof(LookupItemsAsync);
try
{
var dataTable = new DataTable();
dataTable.Columns.Add("ItemNumber", typeof(string));
foreach (var itemNumber in itemNumbers)
{
dataTable.Rows.Add(itemNumber);
}
var itemNumbersCsv = string.Join(",", itemNumbers);
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<Item>(
LotFinderQueries.SqlLookupItems,
new { itemNumbers = dataTable.AsTableValuedParameter("ItemNumberFilterParameter") },
new { itemNumbers = itemNumbersCsv },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
@@ -75,17 +69,12 @@ public partial class LotFinderRepository
const string operation = nameof(LookupWorkordersAsync);
try
{
var dataTable = new DataTable();
dataTable.Columns.Add("WorkOrderNumber", typeof(long));
foreach (var workOrderNumber in workorderNumbers)
{
dataTable.Rows.Add(workOrderNumber);
}
var workOrderNumbersCsv = string.Join(",", workorderNumbers);
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<WorkOrder>(
LotFinderQueries.SqlLookupWorkorders,
new { workOrderNumbers = dataTable.AsTableValuedParameter("WorkOrderFilterParameter") },
new { workOrderNumbers = workOrderNumbersCsv },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
@@ -130,17 +119,12 @@ public partial class LotFinderRepository
const string operation = nameof(LookupWorkCentersAsync);
try
{
var dataTable = new DataTable();
dataTable.Columns.Add("Code", typeof(string));
foreach (var code in codes)
{
dataTable.Rows.Add(code);
}
var workCenterCodesCsv = string.Join(",", codes);
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<WorkCenter>(
LotFinderQueries.SqlLookupWorkCenters,
new { workCenterCodes = dataTable.AsTableValuedParameter("WorkCenterFilterParameter") },
new { workCenterCodes = workCenterCodesCsv },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
@@ -185,17 +169,12 @@ public partial class LotFinderRepository
const string operation = nameof(LookupProfitCentersAsync);
try
{
var dataTable = new DataTable();
dataTable.Columns.Add("Code", typeof(string));
foreach (var code in codes)
{
dataTable.Rows.Add(code);
}
var profitCenterCodesCsv = string.Join(",", codes);
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<ProfitCenter>(
LotFinderQueries.SqlLookupProfitCenters,
new { profitCenterCodes = dataTable.AsTableValuedParameter("ProfitCenterFilterParameter") },
new { profitCenterCodes = profitCenterCodesCsv },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
@@ -240,17 +219,12 @@ public partial class LotFinderRepository
const string operation = nameof(LookupUsersAsync);
try
{
var dataTable = new DataTable();
dataTable.Columns.Add("UserName", typeof(string));
foreach (var userId in userIds)
{
dataTable.Rows.Add(userId);
}
var userIdsCsv = string.Join(",", userIds);
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<JdeUser>(
LotFinderQueries.SqlLookupUsers,
new { userIDs = dataTable.AsTableValuedParameter("OperatorFilterParameter") },
new { userIds = userIdsCsv },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
@@ -271,18 +245,13 @@ public partial class LotFinderRepository
const string operation = nameof(LookupLotsAsync);
try
{
var dataTable = new DataTable();
dataTable.Columns.Add("ComponentLotNumber", typeof(string));
dataTable.Columns.Add("ItemNumber", typeof(string));
foreach (var lot in lots)
{
dataTable.Rows.Add(lot.LotNumber, lot.ItemNumber);
}
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 { lotNumbers = dataTable.AsTableValuedParameter("ComponentLotFilterParameter") },
new { lotsJson },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}