// ----------------------------------------------------------------------------- // PostgresArtifactIndexRepository.Index.cs // Sprint: SPRINT_20260222_077_Artifact_infrastructure_dal_to_efcore // Task: ARTIF-EF-03 - Convert DAL repositories to EF Core // Description: Index write operations for the artifact repository (EF Core) // ----------------------------------------------------------------------------- using Microsoft.EntityFrameworkCore; namespace StellaOps.Artifact.Infrastructure; public sealed partial class PostgresArtifactIndexRepository { /// public async Task IndexAsync(ArtifactIndexEntry entry, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(entry); // The original SQL used INSERT ... ON CONFLICT DO UPDATE (multi-column conflict clause). // Using ExecuteSqlRawAsync to preserve the exact upsert semantics per cutover strategy guidance. await using var dbContext = await CreateWriteContextAsync(ct); await dbContext.Database.ExecuteSqlRawAsync( """ INSERT INTO evidence.artifact_index ( id, tenant_id, bom_ref, serial_number, artifact_id, storage_key, artifact_type, content_type, sha256, size_bytes, created_at ) VALUES ( {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10} ) ON CONFLICT (tenant_id, bom_ref, serial_number, artifact_id) DO UPDATE SET storage_key = EXCLUDED.storage_key, artifact_type = EXCLUDED.artifact_type, content_type = EXCLUDED.content_type, sha256 = EXCLUDED.sha256, size_bytes = EXCLUDED.size_bytes, updated_at = NOW(), is_deleted = FALSE, deleted_at = NULL """, entry.Id, entry.TenantId, entry.BomRef, entry.SerialNumber, entry.ArtifactId, entry.StorageKey, entry.Type.ToString(), entry.ContentType, entry.Sha256, entry.SizeBytes, entry.CreatedAt.UtcDateTime, ct).ConfigureAwait(false); } }