using SqlSugar;
namespace FoodLabeling.Application.Helpers;
///
/// 探测 fl_label.AppliedRegionType / fl_label_region 是否已落库,兼容未执行 DDL 的环境。
///
public static class LabelRegionSchemaHelper
{
private static LabelRegionSchemaStatus? _cached;
public sealed class LabelRegionSchemaStatus
{
public bool HasAppliedRegionTypeColumn { get; init; }
public bool HasLabelRegionTable { get; init; }
public bool IsFullSchema => HasAppliedRegionTypeColumn && HasLabelRegionTable;
}
public static async Task GetStatusAsync(ISqlSugarClient db)
{
if (_cached is not null)
{
return _cached;
}
var colCount = await db.Ado.GetIntAsync(
"""
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'fl_label'
AND COLUMN_NAME = 'AppliedRegionType'
""");
var tableCount = await db.Ado.GetIntAsync(
"""
SELECT COUNT(*)
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'fl_label_region'
""");
_cached = new LabelRegionSchemaStatus
{
HasAppliedRegionTypeColumn = colCount > 0,
HasLabelRegionTable = tableCount > 0
};
return _cached;
}
/// 单元测试或切换库后调用。
public static void ResetCacheForTests() => _cached = null;
public static async Task GetAppliedRegionTypeForLabelAsync(
ISqlSugarClient db,
string labelId,
string? fallback = null)
{
var map = await GetAppliedRegionTypesForLabelsAsync(db, new List { labelId });
if (map.TryGetValue(labelId, out var type) && !string.IsNullOrWhiteSpace(type))
{
return type.Trim();
}
return string.IsNullOrWhiteSpace(fallback)
? LabelRegionScopeHelper.AppliedRegionSpecified
: fallback.Trim();
}
public static async Task> GetAppliedRegionTypesForLabelsAsync(
ISqlSugarClient db,
IReadOnlyList labelIds)
{
var result = new Dictionary(StringComparer.Ordinal);
if (labelIds.Count == 0)
{
return result;
}
foreach (var id in labelIds)
{
result[id] = LabelRegionScopeHelper.AppliedRegionSpecified;
}
var status = await GetStatusAsync(db);
if (!status.HasAppliedRegionTypeColumn)
{
return result;
}
var ids = labelIds.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim()).Distinct().ToList();
if (ids.Count == 0)
{
return result;
}
var rows = await db.Ado.SqlQueryAsync(
"SELECT Id, AppliedRegionType FROM fl_label WHERE Id IN (@ids)",
new { ids });
foreach (var row in rows)
{
if (string.IsNullOrWhiteSpace(row.Id))
{
continue;
}
result[row.Id] = string.IsNullOrWhiteSpace(row.AppliedRegionType)
? LabelRegionScopeHelper.AppliedRegionSpecified
: row.AppliedRegionType.Trim();
}
return result;
}
public static async Task SetAppliedRegionTypeAsync(
ISqlSugarClient db,
string labelId,
string appliedRegionType)
{
var status = await GetStatusAsync(db);
if (!status.HasAppliedRegionTypeColumn || string.IsNullOrWhiteSpace(labelId))
{
return;
}
await db.Ado.ExecuteCommandAsync(
"UPDATE fl_label SET AppliedRegionType = @type WHERE Id = @id",
new { type = appliedRegionType.Trim(), id = labelId.Trim() });
}
private sealed class LabelAppliedRegionRow
{
public string Id { get; set; } = string.Empty;
public string? AppliedRegionType { get; set; }
}
}