Files

70 lines
2.3 KiB
C#

using Microsoft.EntityFrameworkCore;
public class ExternalIdentifierService : IExternalIdentifierService
{
private readonly AppDbContext _db;
public ExternalIdentifierService(AppDbContext db) => _db = db;
public async Task<Guid?> 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;
}
}