fix(transport): case-insensitive remaining library lookups; base-only template reads for import targets (ScadaBridge#95)
- Preview matches template folders, shared scripts, external systems, SMTP (by Host) and SMS (by AccountSid) with the #93 ToNameLookup comparer (OrdinalIgnoreCase, first wins, never throws), matching SQL Server's case-insensitive collation, so a differently-cased target row is reported as a conflict instead of New. - Apply-side in-memory lookups do the same: ApplyTemplateFoldersAsync, the template folder-id map, ResolveFolderParentEdgesAsync, ApplySmtpConfigsAsync and ApplySmsConfigsAsync. An Overwrite now updates the existing row instead of adding a duplicate (folder names are only unique per parent, so the old ToDictionary could also throw). - New ITemplateEngineRepository.GetBaseTemplatesWithChildrenAsync filters IsDerived in SQL. Preview and the Overwrite load in ApplyTemplatesAsync use it, so a derived slot template that shares a bundled name is never the import target. GetTemplatesWithChildrenAsync is unchanged for the id-keyed callers (export closure, rewire passes), which can need derived rows. Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
+11
-2
@@ -53,8 +53,17 @@ public class TemplateEngineRepository : ITemplateEngineRepository
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<Template>> GetTemplatesWithChildrenAsync(
|
||||
public Task<IReadOnlyList<Template>> GetTemplatesWithChildrenAsync(
|
||||
IEnumerable<string> names, CancellationToken cancellationToken = default)
|
||||
=> GetTemplatesWithChildrenAsync(names, baseOnly: false, cancellationToken);
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IReadOnlyList<Template>> GetBaseTemplatesWithChildrenAsync(
|
||||
IEnumerable<string> names, CancellationToken cancellationToken = default)
|
||||
=> GetTemplatesWithChildrenAsync(names, baseOnly: true, cancellationToken);
|
||||
|
||||
private async Task<IReadOnlyList<Template>> GetTemplatesWithChildrenAsync(
|
||||
IEnumerable<string> names, bool baseOnly, CancellationToken cancellationToken)
|
||||
{
|
||||
// Bulk lookup replaces the per-name N+1 in
|
||||
// BundleImporter.PreviewAsync. Filter out null / empty / duplicate
|
||||
@@ -67,7 +76,7 @@ public class TemplateEngineRepository : ITemplateEngineRepository
|
||||
if (distinct.Length == 0) return Array.Empty<Template>();
|
||||
|
||||
return await _context.Templates
|
||||
.Where(t => distinct.Contains(t.Name))
|
||||
.Where(t => distinct.Contains(t.Name) && (!baseOnly || !t.IsDerived))
|
||||
.Include(t => t.Attributes)
|
||||
.Include(t => t.Alarms)
|
||||
.Include(t => t.Scripts)
|
||||
|
||||
Reference in New Issue
Block a user