Repository navigation
Expand file tree
/
Copy pathIReadRepository{TView}.cs
More file actions
57 lines (48 loc) · 3.07 KB
/
Copy pathIReadRepository{TView}.cs
File metadata and controls
57 lines (48 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using System.Linq.Expressions;
using Norse.Abstractions.Contracts;
namespace Norse.Abstractions.Backend;
/// <summary>
/// The consumer-side read contract for a well (well-and-wire spec §3.2). Every member returns
/// <see cref="Outcome{T}" />; <c>Succeeded ⇒ value is present</c> — absence is a
/// <see cref="Problem" /> (<see cref="ErrorCategory.NotFound" />), never a null. Consumption is
/// <see cref="Outcome{T}.Match{TResult}" />: acceptability of absence is a call-site judgment,
/// never marshalled into the envelope. <typeparamref name="TView" /> is deliberately unconstrained —
/// the entity-side <see cref="IViewBearer{TView}" /> constraint belongs to the implementation.
/// </summary>
/// <typeparam name="TView">The well's read-model document type.</typeparam>
public interface IReadRepository<TView> where TView : notnull
{
/// <summary>
/// Identity path — filters on the root PK internally; no caller-expressed predicate, so the scan cannot be
/// written by accident. Absence → <see cref="ErrorCategory.NotFound" />.
/// </summary>
Task<Outcome<TView>> GetAsync(Guid id, CancellationToken cancellationToken = default);
/// <summary>Identity path with SQL-side projection.</summary>
Task<Outcome<TProjection>> GetAsync<TProjection>(Guid id, Expression<Func<TView, TProjection>> projection,
CancellationToken cancellationToken = default)
where TProjection : notnull;
/// <summary>
/// Asserts exactly one match: 0 → <see cref="ErrorCategory.NotFound" />; more →
/// <see cref="ErrorCategory.MultipleMatches" />.
/// </summary>
Task<Outcome<TView>> SingleAsync(Expression<Func<TView, bool>> predicate,
CancellationToken cancellationToken = default);
/// <summary>Asserts exactly one match, with SQL-side projection.</summary>
Task<Outcome<TProjection>> SingleAsync<TProjection>(Expression<Func<TView, bool>> predicate,
Expression<Func<TView, TProjection>> projection, CancellationToken cancellationToken = default)
where TProjection : notnull;
/// <summary>Asserts at least one match: 0 → <see cref="ErrorCategory.NotFound" />.</summary>
Task<Outcome<TView>> FirstAsync(Expression<Func<TView, bool>> predicate,
CancellationToken cancellationToken = default);
/// <summary>Asserts at least one match, with SQL-side projection.</summary>
Task<Outcome<TProjection>> FirstAsync<TProjection>(Expression<Func<TView, bool>> predicate,
Expression<Func<TView, TProjection>> projection, CancellationToken cancellationToken = default)
where TProjection : notnull;
/// <summary>Set query — asserts nothing, so emptiness is data: an empty list is a value, never a <see cref="Problem" />.</summary>
Task<Outcome<IReadOnlyList<TView>>> ListAsync(Expression<Func<TView, bool>> predicate,
CancellationToken cancellationToken = default);
/// <summary>Set query with SQL-side projection.</summary>
Task<Outcome<IReadOnlyList<TProjection>>> ListAsync<TProjection>(Expression<Func<TView, bool>> predicate,
Expression<Func<TView, TProjection>> projection, CancellationToken cancellationToken = default)
where TProjection : notnull;
}