using Microsoft.EntityFrameworkCore; public class ExternalIdentifierService : IExternalIdentifierService { private readonly AppDbContext _db; public ExternalIdentifierService(AppDbContext db) => _db = db; public async Task ResolveInternalIdAsync( ExternalResourceType resourceType, string system, string value) { var row = await _db.ExternalResourceIdentifiers .AsNoTracking() .FirstOrDefaultAsync(e => e.ResourceType == resourceType && e.System == system && e.Value == value); return row?.InternalId; } public async Task LinkAsync( ExternalResourceType resourceType, Guid internalId, string system, string value) { var existing = await _db.ExternalResourceIdentifiers .FirstOrDefaultAsync(e => e.ResourceType == resourceType && e.System == system && e.Value == value); if (existing is not null) { if (existing.InternalId != internalId) throw new ConflictException( $"Identifier {system}|{value} is already linked to a different internal resource.", "IDENTIFIER_ALREADY_LINKED"); return; } _db.ExternalResourceIdentifiers.Add(new ExternalResourceIdentifier { Id = Guid.NewGuid(), ResourceType = resourceType, InternalId = internalId, System = system, Value = value, CreatedAt = DateTimeOffset.UtcNow }); await _db.SaveChangesAsync(); } public async Task<(string System, string Value)?> FindPrimaryIdentifierAsync( ExternalResourceType resourceType, Guid internalId, string[] acceptedSystems) { var rows = await _db.ExternalResourceIdentifiers .AsNoTracking() .Where(e => e.ResourceType == resourceType && e.InternalId == internalId) .ToListAsync(); foreach (var system in acceptedSystems) { var match = rows.FirstOrDefault(r => r.System == system); if (match is not null) return (match.System, match.Value); } return rows.Count > 0 ? (rows[0].System, rows[0].Value) : null; } }