using Microsoft.EntityFrameworkCore; using ZB.MOM.WW.ScadaBridge.Commons.Entities.Instances; using ZB.MOM.WW.ScadaBridge.Commons.Entities.Scripts; using ZB.MOM.WW.ScadaBridge.Commons.Entities.Templates; using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories; using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Services; using ZB.MOM.WW.ScadaBridge.Commons.Types.Templates; namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Repositories; public class TemplateEngineRepository : ITemplateEngineRepository { private readonly ScadaBridgeDbContext _context; private readonly ITemplateGraphWatermark _watermark; /// /// Initializes a new instance of the TemplateEngineRepository class. /// /// The database context used to access template and instance data. /// /// Process-wide template/instance version watermark. This repository is the /// single unit-of-work through which EVERY template-graph mutation commits — /// TemplateService, the ManagementActor native-alarm-source /// handlers, and the Transport bundle importer all funnel through the same /// — so bumping here (rather than in each /// caller) is the only placement that cannot be bypassed. /// public TemplateEngineRepository(ScadaBridgeDbContext context, ITemplateGraphWatermark watermark) { _context = context ?? throw new ArgumentNullException(nameof(context)); _watermark = watermark ?? throw new ArgumentNullException(nameof(watermark)); } // Template /// public async Task GetTemplateByIdAsync(int id, CancellationToken cancellationToken = default) { return await _context.Templates .Include(t => t.Attributes) .Include(t => t.Alarms) .Include(t => t.Scripts) .Include(t => t.Compositions) .Include(t => t.NativeAlarmSources) .AsSplitQuery() .FirstOrDefaultAsync(t => t.Id == id, cancellationToken); } /// public async Task GetTemplateWithChildrenAsync(int id, CancellationToken cancellationToken = default) { return await GetTemplateByIdAsync(id, cancellationToken); } /// public async Task> GetTemplatesWithChildrenAsync( IEnumerable names, CancellationToken cancellationToken = default) { // Bulk lookup replaces the per-name N+1 in // BundleImporter.PreviewAsync. Filter out null / empty / duplicate // names before the query so EF emits a clean, deduplicated IN clause. if (names is null) return Array.Empty