feat(templates): GetTemplateStubsAsync untracked identity/edge projection
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Instances;
|
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Instances;
|
||||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Scripts;
|
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Scripts;
|
||||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Templates;
|
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Templates;
|
||||||
|
using ZB.MOM.WW.ScadaBridge.Commons.Types.Templates;
|
||||||
|
|
||||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories;
|
namespace ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories;
|
||||||
|
|
||||||
@@ -55,6 +56,12 @@ public interface ITemplateEngineRepository
|
|||||||
/// <returns>A task that resolves to a read-only list of all templates without script bodies.</returns>
|
/// <returns>A task that resolves to a read-only list of all templates without script bodies.</returns>
|
||||||
Task<IReadOnlyList<Template>> GetAllTemplatesForAnalysisAsync(CancellationToken cancellationToken = default);
|
Task<IReadOnlyList<Template>> GetAllTemplatesForAnalysisAsync(CancellationToken cancellationToken = default);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Returns an untracked identity/edge projection of every template (no children), ordered by name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">Cancellation token.</param>
|
||||||
|
/// <returns>A task that resolves to a read-only list of template stubs.</returns>
|
||||||
|
Task<IReadOnlyList<TemplateStub>> GetTemplateStubsAsync(CancellationToken cancellationToken = default);
|
||||||
|
/// <summary>
|
||||||
/// Database-side paged listing of templates as row summaries (child
|
/// Database-side paged listing of templates as row summaries (child
|
||||||
/// collections reduced to counts, no script bodies). Backs the
|
/// collections reduced to counts, no script bodies). Backs the
|
||||||
/// <c>ListTemplates</c> management command, which previously materialised
|
/// <c>ListTemplates</c> management command, which previously materialised
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
namespace ZB.MOM.WW.ScadaBridge.Commons.Types.Templates;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Lightweight template identity/edge projection (no attributes, alarms, scripts or compositions)
|
||||||
|
/// for callers that only need names and the inheritance/folder/ownership edges.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Id">Template ID.</param>
|
||||||
|
/// <param name="Name">Template name.</param>
|
||||||
|
/// <param name="ParentTemplateId">Base template, if any.</param>
|
||||||
|
/// <param name="FolderId">Containing folder, if any.</param>
|
||||||
|
/// <param name="IsDerived">True for auto-derived composition templates.</param>
|
||||||
|
/// <param name="OwnerCompositionId">Owning composition row for derived templates.</param>
|
||||||
|
public sealed record TemplateStub(
|
||||||
|
int Id,
|
||||||
|
string Name,
|
||||||
|
int? ParentTemplateId,
|
||||||
|
int? FolderId,
|
||||||
|
bool IsDerived,
|
||||||
|
int? OwnerCompositionId);
|
||||||
+10
@@ -90,6 +90,16 @@ public class TemplateEngineRepository : ITemplateEngineRepository
|
|||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task<IReadOnlyList<TemplateStub>> GetTemplateStubsAsync(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return await _context.Templates
|
||||||
|
.AsNoTracking()
|
||||||
|
.OrderBy(t => t.Name)
|
||||||
|
.Select(t => new TemplateStub(t.Id, t.Name, t.ParentTemplateId, t.FolderId, t.IsDerived, t.OwnerCompositionId))
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
// Two deliberate departures from <see cref="GetAllTemplatesAsync"/>:
|
// Two deliberate departures from <see cref="GetAllTemplatesAsync"/>:
|
||||||
// <list type="number">
|
// <list type="number">
|
||||||
|
|||||||
+21
@@ -31,6 +31,27 @@ public class TemplateEngineRepositoryTests : IDisposable
|
|||||||
_context.Dispose();
|
_context.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Verifies the stub projection carries identity and edges and leaves nothing tracked.</summary>
|
||||||
|
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||||
|
[Fact]
|
||||||
|
public async Task GetTemplateStubs_ProjectsEdgesUntrackedOrderedByName()
|
||||||
|
{
|
||||||
|
var baseT = new Template("Base");
|
||||||
|
_context.Templates.Add(baseT);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
_context.Templates.Add(new Template("Alpha") { ParentTemplateId = baseT.Id });
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
_context.ChangeTracker.Clear();
|
||||||
|
|
||||||
|
var stubs = await _repository.GetTemplateStubsAsync();
|
||||||
|
|
||||||
|
Assert.Equal(new[] { "Alpha", "Base" }, stubs.Select(s => s.Name));
|
||||||
|
Assert.Equal(baseT.Id, stubs[0].ParentTemplateId);
|
||||||
|
Assert.Null(stubs[1].ParentTemplateId);
|
||||||
|
Assert.False(stubs[0].IsDerived);
|
||||||
|
Assert.Empty(_context.ChangeTracker.Entries());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Verifies that the topology page is bounded, filtered and returned untracked.</summary>
|
/// <summary>Verifies that the topology page is bounded, filtered and returned untracked.</summary>
|
||||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
Reference in New Issue
Block a user