99 lines
3.5 KiB
C#
99 lines
3.5 KiB
C#
#nullable enable
|
|
|
|
using System.Data;
|
|
using MMoneyCoderSharp.Data;
|
|
|
|
namespace MBN_STOCK_WEBVIEW.DbWriteSmoke;
|
|
|
|
/// <summary>
|
|
/// The legacy deletion workflows remove child rows by numeric parent key. This
|
|
/// read-only guard proves a newly suggested key has no pre-existing orphaned
|
|
/// children before a smoke record can adopt that key.
|
|
/// </summary>
|
|
internal sealed class ExistingChildRowGuard
|
|
{
|
|
private const string ResultColumn = "ROW_COUNT";
|
|
|
|
private readonly IDataQueryExecutor _executor;
|
|
|
|
internal ExistingChildRowGuard(IDataQueryExecutor executor)
|
|
{
|
|
_executor = executor ?? throw new ArgumentNullException(nameof(executor));
|
|
}
|
|
|
|
internal Task EnsureNamedPlaylistChildrenAbsentAsync(
|
|
string programCode,
|
|
CancellationToken cancellationToken) =>
|
|
EnsureZeroAsync(
|
|
DataSourceKind.Oracle,
|
|
"DB_WRITE_SMOKE_PLAYLIST_CHILD_PREFLIGHT",
|
|
"SELECT TO_CHAR(COUNT(*)) ROW_COUNT FROM PLAY_LIST WHERE PG_CODE = :parent_code",
|
|
programCode,
|
|
cancellationToken);
|
|
|
|
internal Task EnsureThemeChildrenAbsentAsync(
|
|
ThemeMarket market,
|
|
string themeCode,
|
|
CancellationToken cancellationToken) =>
|
|
market switch
|
|
{
|
|
ThemeMarket.Krx => EnsureZeroAsync(
|
|
DataSourceKind.Oracle,
|
|
"DB_WRITE_SMOKE_KRX_THEME_CHILD_PREFLIGHT",
|
|
"SELECT TO_CHAR(COUNT(*)) ROW_COUNT FROM SB_ITEM WHERE SB_M_CODE = :parent_code",
|
|
themeCode,
|
|
cancellationToken),
|
|
ThemeMarket.Nxt => EnsureZeroAsync(
|
|
DataSourceKind.MariaDb,
|
|
"DB_WRITE_SMOKE_NXT_THEME_CHILD_PREFLIGHT",
|
|
"SELECT CAST(COUNT(*) AS CHAR) ROW_COUNT FROM SB_ITEM WHERE SB_M_CODE = @parent_code",
|
|
themeCode,
|
|
cancellationToken),
|
|
_ => throw new ArgumentOutOfRangeException(nameof(market))
|
|
};
|
|
|
|
internal Task EnsureExpertChildrenAbsentAsync(
|
|
string expertCode,
|
|
CancellationToken cancellationToken) =>
|
|
EnsureZeroAsync(
|
|
DataSourceKind.Oracle,
|
|
"DB_WRITE_SMOKE_EXPERT_CHILD_PREFLIGHT",
|
|
"SELECT TO_CHAR(COUNT(*)) ROW_COUNT FROM RECOMMEND_LIST WHERE RC_CODE = :parent_code",
|
|
expertCode,
|
|
cancellationToken);
|
|
|
|
private async Task EnsureZeroAsync(
|
|
DataSourceKind source,
|
|
string queryName,
|
|
string sql,
|
|
string parentCode,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(parentCode);
|
|
var spec = new DataQuerySpec(
|
|
sql,
|
|
[new DataQueryParameter("parent_code", parentCode, DbType.String)]);
|
|
spec.ValidateFor(source);
|
|
var table = await _executor.ExecuteAsync(
|
|
source,
|
|
queryName,
|
|
spec,
|
|
cancellationToken).ConfigureAwait(false);
|
|
|
|
if (table is null ||
|
|
table.Columns.Count != 1 ||
|
|
table.Rows.Count != 1 ||
|
|
!string.Equals(
|
|
table.Columns[0].ColumnName,
|
|
ResultColumn,
|
|
StringComparison.Ordinal) ||
|
|
table.Columns[0].DataType != typeof(string) ||
|
|
table.Rows[0][0] is not string count ||
|
|
!string.Equals(count, "0", StringComparison.Ordinal))
|
|
{
|
|
throw new InvalidOperationException(
|
|
"A suggested numeric key has existing child rows or an invalid preflight result.");
|
|
}
|
|
}
|
|
}
|