Files
ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Repositories/NotificationRepository.cs
T
Joseph Doherty 7c74bbe4b5 fix(transport): close 5 residual import/export fidelity holes surfaced by the round-trip guard (T8)
The Task-8 reflection round-trip suite exposed five silent-data-loss paths in
non-template entity types:
- ExternalSystemDefinition.MaxRetries/RetryDelay dropped on import Add (and Overwrite
  never updated them) — BuildExternalSystem + Overwrite branch now carry both.
- ExternalSystemMethod rows dropped on import Add — a new post-flush
  PersistAddedExternalSystemMethodsAsync pass adds them (the entity has no parent
  nav, so an Add can't cascade; idempotent vs the inline Overwrite sync).
- NotificationRecipient dropped on export — GetNotificationListByIdAsync now
  Include(Recipients) instead of a bare FindAsync.
- TemplateFolder.ParentFolderId flattened on import Add — a new
  ResolveFolderParentEdgesAsync second-pass rewire resolves ParentName→id,
  mirroring the template inheritance/composition rewires.

Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj
2026-07-09 17:44:12 -04:00

127 lines
6.6 KiB
C#

using Microsoft.EntityFrameworkCore;
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Notifications;
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories;
namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Repositories;
public class NotificationRepository : INotificationRepository
{
private readonly ScadaBridgeDbContext _context;
/// <summary>Initializes a new instance of the NotificationRepository class.</summary>
/// <param name="context">The database context.</param>
public NotificationRepository(ScadaBridgeDbContext context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
}
/// <inheritdoc />
public async Task<NotificationList?> GetNotificationListByIdAsync(int id, CancellationToken cancellationToken = default)
// Eager-load Recipients: single-list selection feeds the Transport exporter,
// which serializes the recipient collection — a FindAsync without the Include
// exported a recipient-less list (silent data loss).
=> await _context.Set<NotificationList>()
.Include(n => n.Recipients)
.FirstOrDefaultAsync(n => n.Id == id, cancellationToken);
/// <inheritdoc />
public async Task<IReadOnlyList<NotificationList>> GetAllNotificationListsAsync(CancellationToken cancellationToken = default)
=> await _context.Set<NotificationList>().Include(n => n.Recipients).ToListAsync(cancellationToken);
/// <inheritdoc />
public async Task<NotificationList?> GetListByNameAsync(string name, CancellationToken cancellationToken = default)
=> await _context.Set<NotificationList>().FirstOrDefaultAsync(l => l.Name == name, cancellationToken);
/// <inheritdoc />
public async Task AddNotificationListAsync(NotificationList list, CancellationToken cancellationToken = default)
=> await _context.Set<NotificationList>().AddAsync(list, cancellationToken);
/// <inheritdoc />
public Task UpdateNotificationListAsync(NotificationList list, CancellationToken cancellationToken = default)
{ _context.Set<NotificationList>().Update(list); return Task.CompletedTask; }
/// <inheritdoc />
public async Task DeleteNotificationListAsync(int id, CancellationToken cancellationToken = default)
{
var entity = await GetNotificationListByIdAsync(id, cancellationToken);
if (entity != null) _context.Set<NotificationList>().Remove(entity);
}
/// <inheritdoc />
public async Task<NotificationRecipient?> GetRecipientByIdAsync(int id, CancellationToken cancellationToken = default)
=> await _context.Set<NotificationRecipient>().FindAsync(new object[] { id }, cancellationToken);
/// <inheritdoc />
public async Task<IReadOnlyList<NotificationRecipient>> GetRecipientsByListIdAsync(int notificationListId, CancellationToken cancellationToken = default)
=> await _context.Set<NotificationRecipient>().Where(r => r.NotificationListId == notificationListId).ToListAsync(cancellationToken);
/// <inheritdoc />
public async Task AddRecipientAsync(NotificationRecipient recipient, CancellationToken cancellationToken = default)
=> await _context.Set<NotificationRecipient>().AddAsync(recipient, cancellationToken);
/// <inheritdoc />
public Task UpdateRecipientAsync(NotificationRecipient recipient, CancellationToken cancellationToken = default)
{ _context.Set<NotificationRecipient>().Update(recipient); return Task.CompletedTask; }
/// <inheritdoc />
public async Task DeleteRecipientAsync(int id, CancellationToken cancellationToken = default)
{
var entity = await GetRecipientByIdAsync(id, cancellationToken);
if (entity != null) _context.Set<NotificationRecipient>().Remove(entity);
}
/// <inheritdoc />
public async Task<SmtpConfiguration?> GetSmtpConfigurationByIdAsync(int id, CancellationToken cancellationToken = default)
=> await _context.Set<SmtpConfiguration>().FindAsync(new object[] { id }, cancellationToken);
/// <inheritdoc />
public async Task<IReadOnlyList<SmtpConfiguration>> GetAllSmtpConfigurationsAsync(CancellationToken cancellationToken = default)
=> await _context.Set<SmtpConfiguration>().ToListAsync(cancellationToken);
/// <inheritdoc />
public async Task AddSmtpConfigurationAsync(SmtpConfiguration configuration, CancellationToken cancellationToken = default)
=> await _context.Set<SmtpConfiguration>().AddAsync(configuration, cancellationToken);
/// <inheritdoc />
public Task UpdateSmtpConfigurationAsync(SmtpConfiguration configuration, CancellationToken cancellationToken = default)
{ _context.Set<SmtpConfiguration>().Update(configuration); return Task.CompletedTask; }
/// <inheritdoc />
public async Task DeleteSmtpConfigurationAsync(int id, CancellationToken cancellationToken = default)
{
var entity = await GetSmtpConfigurationByIdAsync(id, cancellationToken);
if (entity != null) _context.Set<SmtpConfiguration>().Remove(entity);
}
/// <inheritdoc />
public async Task<SmsConfiguration?> GetSmsConfigurationAsync(CancellationToken cancellationToken = default)
=> await _context.Set<SmsConfiguration>().FirstOrDefaultAsync(cancellationToken);
/// <inheritdoc />
public async Task<SmsConfiguration?> GetSmsConfigurationByIdAsync(int id, CancellationToken cancellationToken = default)
=> await _context.Set<SmsConfiguration>().FindAsync(new object[] { id }, cancellationToken);
/// <inheritdoc />
public async Task<IReadOnlyList<SmsConfiguration>> GetAllSmsConfigurationsAsync(CancellationToken cancellationToken = default)
=> await _context.Set<SmsConfiguration>().ToListAsync(cancellationToken);
/// <inheritdoc />
public async Task AddSmsConfigurationAsync(SmsConfiguration smsConfiguration, CancellationToken cancellationToken = default)
=> await _context.Set<SmsConfiguration>().AddAsync(smsConfiguration, cancellationToken);
/// <inheritdoc />
public Task UpdateSmsConfigurationAsync(SmsConfiguration smsConfiguration, CancellationToken cancellationToken = default)
{ _context.Set<SmsConfiguration>().Update(smsConfiguration); return Task.CompletedTask; }
/// <inheritdoc />
public async Task DeleteSmsConfigurationAsync(int id, CancellationToken cancellationToken = default)
{
var entity = await _context.Set<SmsConfiguration>().FindAsync(new object[] { id }, cancellationToken);
if (entity != null) _context.Set<SmsConfiguration>().Remove(entity);
}
/// <inheritdoc />
public async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
=> await _context.SaveChangesAsync(cancellationToken);
}