PlotDirector/PlotLine/Data/CharacterIntelligenceRepository.cs

74 lines
3.5 KiB
C#

using Dapper;
using PlotLine.Models;
namespace PlotLine.Data;
public interface ICharacterIntelligenceRepository
{
Task<IReadOnlyList<CharacterIntelligenceProfile>> ListProfilesAsync(int importSessionId);
Task<CharacterIntelligenceProfile> UpsertProfileAsync(CharacterIntelligenceProfileSave request);
Task AddEvidenceAsync(CharacterIntelligenceEvidenceSave request);
}
public sealed class CharacterIntelligenceRepository(ISqlConnectionFactory connectionFactory) : ICharacterIntelligenceRepository
{
public async Task<IReadOnlyList<CharacterIntelligenceProfile>> ListProfilesAsync(int importSessionId)
{
using var connection = connectionFactory.CreateConnection();
var rows = await connection.QueryAsync<CharacterIntelligenceProfile>(
"""
SELECT *
FROM dbo.CharacterIntelligenceProfiles
WHERE ImportSessionID = @ImportSessionID
ORDER BY IsRecurring DESC, Confidence DESC, CanonicalName;
""",
new { ImportSessionID = importSessionId });
return rows.ToList();
}
public async Task<CharacterIntelligenceProfile> UpsertProfileAsync(CharacterIntelligenceProfileSave request)
{
using var connection = connectionFactory.CreateConnection();
return await connection.QuerySingleAsync<CharacterIntelligenceProfile>(
"""
MERGE dbo.CharacterIntelligenceProfiles WITH (HOLDLOCK) AS target
USING (SELECT @ImportSessionID AS ImportSessionID, @CanonicalIdentityKey AS CanonicalIdentityKey) AS source
ON target.ImportSessionID = source.ImportSessionID
AND target.CanonicalIdentityKey = source.CanonicalIdentityKey
WHEN MATCHED THEN
UPDATE SET
CanonicalName = @CanonicalName,
ProfileJson = @ProfileJson,
Confidence = @Confidence,
NarrativeImportance = @NarrativeImportance,
IsRecurring = CASE WHEN @IsRecurring = 1 THEN 1 ELSE target.IsRecurring END,
EvidenceVersion = @EvidenceVersion,
LastUpdatedSceneResultID = @SceneResultID,
UpdatedUtc = SYSUTCDATETIME()
WHEN NOT MATCHED THEN
INSERT (ImportSessionID, ProjectID, BookID, CanonicalIdentityKey, CanonicalName, ProfileJson, Confidence, NarrativeImportance, IsRecurring, EvidenceVersion, LastUpdatedSceneResultID)
VALUES (@ImportSessionID, @ProjectID, @BookID, @CanonicalIdentityKey, @CanonicalName, @ProfileJson, @Confidence, @NarrativeImportance, @IsRecurring, @EvidenceVersion, @SceneResultID);
SELECT *
FROM dbo.CharacterIntelligenceProfiles
WHERE ImportSessionID = @ImportSessionID
AND CanonicalIdentityKey = @CanonicalIdentityKey;
""",
request);
}
public async Task AddEvidenceAsync(CharacterIntelligenceEvidenceSave request)
{
using var connection = connectionFactory.CreateConnection();
await connection.ExecuteAsync(
"""
INSERT dbo.CharacterIntelligenceEvidenceEvents
(CharacterIntelligenceProfileID, SceneResultID, FieldName, PreviousValue, NewValue, Evidence, Confidence, IsContradiction, Source)
VALUES
(@CharacterIntelligenceProfileID, @SceneResultID, @FieldName, @PreviousValue, @NewValue, @Evidence, @Confidence, @IsContradiction, @Source);
""",
request);
}
}