Backend (.NET 10): - EventFlow CQRS/Event Sourcing with PostgreSQL - GraphQL.NET API with mutations and queries - Custom ReadModelSqlGenerator for snake_case PostgreSQL columns - Hangfire for background job processing - Integration tests with isolated test databases Frontend (React/Vite): - Initial project structure 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
89 lines
3.2 KiB
C#
89 lines
3.2 KiB
C#
using Books.Api.Domain.Companies;
|
|
using Books.Api.EventFlow.ReadModels;
|
|
using Dapper;
|
|
using Npgsql;
|
|
|
|
namespace Books.Api.EventFlow.Repositories;
|
|
|
|
public class CompanyRepository(NpgsqlDataSource dataSource) : ICompanyRepository
|
|
{
|
|
public async Task<CompanyReadModelDto?> GetByIdAsync(string id, CancellationToken cancellationToken = default)
|
|
{
|
|
await using var connection = await dataSource.OpenConnectionAsync(cancellationToken);
|
|
|
|
const string sql = """
|
|
SELECT
|
|
aggregate_id AS Id,
|
|
name AS Name,
|
|
cvr AS Cvr,
|
|
address AS Address,
|
|
postal_code AS PostalCode,
|
|
city AS City,
|
|
country AS Country,
|
|
fiscal_year_start_month AS FiscalYearStartMonth,
|
|
currency AS Currency,
|
|
vat_registered AS VatRegistered,
|
|
vat_period_frequency AS VatPeriodFrequency,
|
|
create_time AS CreatedAt,
|
|
updated_time AS UpdatedAt
|
|
FROM company_read_models
|
|
WHERE aggregate_id = @Id
|
|
""";
|
|
|
|
return await connection.QuerySingleOrDefaultAsync<CompanyReadModelDto>(sql, new { Id = id });
|
|
}
|
|
|
|
public async Task<IEnumerable<CompanyReadModelDto>> GetByIds(List<CompanyId> ids,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
await using var connection = await dataSource.OpenConnectionAsync(cancellationToken);
|
|
|
|
const string sql = """
|
|
SELECT
|
|
aggregate_id AS Id,
|
|
name AS Name,
|
|
cvr AS Cvr,
|
|
address AS Address,
|
|
postal_code AS PostalCode,
|
|
city AS City,
|
|
country AS Country,
|
|
fiscal_year_start_month AS FiscalYearStartMonth,
|
|
currency AS Currency,
|
|
vat_registered AS VatRegistered,
|
|
vat_period_frequency AS VatPeriodFrequency,
|
|
create_time AS CreatedAt,
|
|
updated_time AS UpdatedAt
|
|
FROM company_read_models
|
|
WHERE aggregate_id = ANY(@Ids)
|
|
""";
|
|
|
|
return await connection.QueryAsync<CompanyReadModelDto>(sql, new { Ids = ids.Select(i => i.Value).ToArray() });
|
|
}
|
|
|
|
public async Task<IReadOnlyList<CompanyReadModelDto>> GetAllAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
await using var connection = await dataSource.OpenConnectionAsync(cancellationToken);
|
|
|
|
const string sql = """
|
|
SELECT
|
|
aggregate_id AS Id,
|
|
name AS Name,
|
|
cvr AS Cvr,
|
|
address AS Address,
|
|
postal_code AS PostalCode,
|
|
city AS City,
|
|
country AS Country,
|
|
fiscal_year_start_month AS FiscalYearStartMonth,
|
|
currency AS Currency,
|
|
vat_registered AS VatRegistered,
|
|
vat_period_frequency AS VatPeriodFrequency,
|
|
create_time AS CreatedAt,
|
|
updated_time AS UpdatedAt
|
|
FROM company_read_models
|
|
ORDER BY name
|
|
""";
|
|
|
|
var result = await connection.QueryAsync<CompanyReadModelDto>(sql);
|
|
return result.ToList();
|
|
}
|
|
}
|