feat(dotnet): migrate core formulas, deploy tools, and blazor admin web app to .NET 10
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (push) Has been cancelled
Quant Engine CI/CD Pipeline / validate-core (pull_request) Has been cancelled
Quant Engine CI/CD Pipeline / validate-ui-and-storage (pull_request) Has been cancelled
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (pull_request) Has been cancelled

This commit is contained in:
2026-06-25 15:52:10 +09:00
parent 9abb8d3bc3
commit 2ba8def9bb
232 changed files with 10825 additions and 65 deletions
@@ -0,0 +1,192 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Dapper;
using QuantEngine.Core.Interfaces;
using QuantEngine.Core.Models;
using QuantEngine.Infrastructure.Data;
namespace QuantEngine.Infrastructure.Repositories
{
public class WorkspaceRepository : IWorkspaceRepository
{
private readonly IDbConnectionFactory _connectionFactory;
public WorkspaceRepository(IDbConnectionFactory connectionFactory)
{
_connectionFactory = connectionFactory;
}
// Settings
public async Task<IEnumerable<Setting>> GetSettingsAsync()
{
using var conn = _connectionFactory.CreateConnection();
return await conn.QueryAsync<Setting>(
"SELECT ordinal, key, value_json as ValueJson, note, updated_at as UpdatedAt FROM quantengine.settings ORDER BY ordinal ASC"
);
}
public async Task<Setting?> GetSettingByKeyAsync(string key)
{
using var conn = _connectionFactory.CreateConnection();
return await conn.QueryFirstOrDefaultAsync<Setting>(
"SELECT ordinal, key, value_json as ValueJson, note, updated_at as UpdatedAt FROM quantengine.settings WHERE key = @Key",
new { Key = key }
);
}
public async Task<bool> UpsertSettingAsync(Setting setting)
{
using var conn = _connectionFactory.CreateConnection();
var affected = await conn.ExecuteAsync(@"
INSERT INTO quantengine.settings (ordinal, key, value_json, note, updated_at)
VALUES (@Ordinal, @Key, @ValueJson, @Note, @UpdatedAt)
ON CONFLICT (key) DO UPDATE SET
ordinal = EXCLUDED.ordinal,
value_json = EXCLUDED.value_json,
note = EXCLUDED.note,
updated_at = EXCLUDED.updated_at",
setting
);
return affected > 0;
}
public async Task<bool> DeleteSettingAsync(string key)
{
using var conn = _connectionFactory.CreateConnection();
var affected = await conn.ExecuteAsync(
"DELETE FROM quantengine.settings WHERE key = @Key",
new { Key = key }
);
return affected > 0;
}
// AccountSnapshot
public async Task<IEnumerable<AccountSnapshot>> GetAccountSnapshotsAsync()
{
using var conn = _connectionFactory.CreateConnection();
return await conn.QueryAsync<AccountSnapshot>(@"
SELECT ordinal, row_json as RowJson, captured_at as CapturedAt, account, account_type as AccountType,
ticker, name, parse_status as ParseStatus, user_confirmed as UserConfirmed, updated_at as UpdatedAt
FROM quantengine.account_snapshot
ORDER BY ordinal ASC"
);
}
public async Task<bool> InsertAccountSnapshotsAsync(IEnumerable<AccountSnapshot> snapshots)
{
using var conn = _connectionFactory.CreateConnection();
conn.Open();
using var tx = conn.BeginTransaction();
try
{
foreach (var snapshot in snapshots)
{
await conn.ExecuteAsync(@"
INSERT INTO quantengine.account_snapshot (ordinal, row_json, captured_at, account, account_type, ticker, name, parse_status, user_confirmed, updated_at)
VALUES (@Ordinal, @RowJson, @CapturedAt, @Account, @AccountType, @Ticker, @Name, @ParseStatus, @UserConfirmed, @UpdatedAt)",
snapshot,
tx
);
}
tx.Commit();
return true;
}
catch
{
tx.Rollback();
throw;
}
}
public async Task<bool> ClearAccountSnapshotsAsync()
{
using var conn = _connectionFactory.CreateConnection();
var affected = await conn.ExecuteAsync("DELETE FROM quantengine.account_snapshot");
return affected >= 0;
}
// WorkspaceApproval
public async Task<IEnumerable<WorkspaceApproval>> GetApprovalsAsync()
{
using var conn = _connectionFactory.CreateConnection();
return await conn.QueryAsync<WorkspaceApproval>(@"
SELECT domain, target_ref as TargetRef, status, approved_by as ApprovedBy,
approved_at as ApprovedAt, note, updated_at as UpdatedAt
FROM quantengine.workspace_approval_v2"
);
}
public async Task<WorkspaceApproval?> GetApprovalAsync(string domain, string targetRef)
{
using var conn = _connectionFactory.CreateConnection();
return await conn.QueryFirstOrDefaultAsync<WorkspaceApproval>(@"
SELECT domain, target_ref as TargetRef, status, approved_by as ApprovedBy,
approved_at as ApprovedAt, note, updated_at as UpdatedAt
FROM quantengine.workspace_approval_v2
WHERE domain = @Domain AND target_ref = @TargetRef",
new { Domain = domain, TargetRef = targetRef }
);
}
public async Task<bool> UpsertApprovalAsync(WorkspaceApproval approval)
{
using var conn = _connectionFactory.CreateConnection();
var affected = await conn.ExecuteAsync(@"
INSERT INTO quantengine.workspace_approval_v2 (domain, target_ref, status, approved_by, approved_at, note, updated_at)
VALUES (@Domain, @TargetRef, @Status, @ApprovedBy, @ApprovedAt, @Note, @UpdatedAt)
ON CONFLICT (domain, target_ref) DO UPDATE SET
status = EXCLUDED.status,
approved_by = EXCLUDED.approved_by,
approved_at = EXCLUDED.approved_at,
note = EXCLUDED.note,
updated_at = EXCLUDED.updated_at",
approval
);
return affected > 0;
}
// WorkspaceLock
public async Task<IEnumerable<WorkspaceLock>> GetLocksAsync()
{
using var conn = _connectionFactory.CreateConnection();
return await conn.QueryAsync<WorkspaceLock>(@"
SELECT domain, target_ref as TargetRef, locked_by as LockedBy, reason, locked_at as LockedAt
FROM quantengine.workspace_lock"
);
}
public async Task<WorkspaceLock?> GetLockAsync(string domain, string targetRef)
{
using var conn = _connectionFactory.CreateConnection();
return await conn.QueryFirstOrDefaultAsync<WorkspaceLock>(@"
SELECT domain, target_ref as TargetRef, locked_by as LockedBy, reason, locked_at as LockedAt
FROM quantengine.workspace_lock
WHERE domain = @Domain AND target_ref = @TargetRef",
new { Domain = domain, TargetRef = targetRef }
);
}
public async Task<bool> AcquireLockAsync(WorkspaceLock @lock)
{
using var conn = _connectionFactory.CreateConnection();
var affected = await conn.ExecuteAsync(@"
INSERT INTO quantengine.workspace_lock (domain, target_ref, locked_by, reason, locked_at)
VALUES (@Domain, @TargetRef, @LockedBy, @Reason, @LockedAt)
ON CONFLICT (domain, target_ref) DO NOTHING",
@lock
);
return affected > 0;
}
public async Task<bool> ReleaseLockAsync(string domain, string targetRef)
{
using var conn = _connectionFactory.CreateConnection();
var affected = await conn.ExecuteAsync(
"DELETE FROM quantengine.workspace_lock WHERE domain = @Domain AND target_ref = @TargetRef",
new { Domain = domain, TargetRef = targetRef }
);
return affected > 0;
}
}
}