2using System.Collections.Generic;
4using System.Linq.Expressions;
6using System.Threading.Tasks;
8using Microsoft.EntityFrameworkCore;
21 where TResult : notnull
51 ArgumentNullException.ThrowIfNull(projection);
52 ArgumentNullException.ThrowIfNull(inputs);
54 if (inputs.Length == 0)
55 return new Dictionary<long, AuthorityResponse<TResult>>();
57 var firstProjectable = inputs[0];
58 var workingSet = projection(firstProjectable.query);
59 foreach (var projectable
in inputs.Skip(1))
61 if (firstProjectable.resultMapper != projectable.resultMapper)
62 throw new InvalidOperationException($
"Different implementations of {nameof(resultMapper)} in combined {firstProjectable.GetType().Name}.");
63 if (firstProjectable.selector != projectable.selector)
64 throw new InvalidOperationException($
"Different implementations of {nameof(selector)} in combined {firstProjectable.GetType().Name}.");
66 workingSet = workingSet.Union(projection(projectable.query));
69 using var cts = CancellationTokenSource.CreateLinkedTokenSource(inputs.Select(projectable => projectable.cancellationToken).ToArray());
70 var finalQueryable = workingSet
73 return await finalQueryable
76 result => firstProjectable.resultMapper(result.Projected));
118 Result = projected.Result,
126 makeProjectedGeneric,
135 Queried = (TSelection)projected.
Queried!,
136 Result = projected.Result,
149 Expression<Func<ProjectedPair<TQueried, TResult>,
long>> idSelector = projected => projected.Queried.Id!.Value;
152 var selection = Expression.Invoke(
selector, parameter);
153 var
id = Expression.Invoke(idSelector, parameter);
157 var memberInitExpr = Expression.MemberInit(
158 Expression.New(ourType),
166 var finalExpr = Expression.Lambda<Func<ProjectedPair<TQueried, TResult>,
CombinedProjection>>(memberInitExpr, parameter);
184 this.query =
query ??
throw new ArgumentNullException(nameof(
query));
185 this.selector =
selector ??
throw new ArgumentNullException(nameof(
selector));
197 ArgumentNullException.ThrowIfNull(projection);
198 var selection = await projection(
query)
212 public required
long Id {
get; init; }
Common base of entities with IDs.
Represents a response from an authority.
DTO for selecting the Id from TQueried alongside the selection ProjectedPair<TQueried,...
required ProjectedPair< object?, TResult > Projected
The selection/TResult ProjectedPair<TQueried, TResult>.
required long Id
The EntityId.Id of TQueried .
A projectable TResult based on an underlying TQueried .
readonly Expression< Func< ProjectedPair< TQueried, TResult >, ProjectedPair< object?, TResult > > > selector
The selector for the ProjectedPair<TQueried, TResult> data required by the resultMapper.
async ValueTask< AuthorityResponse< TResult > > Resolve(Func< IQueryable< TQueried >, IQueryable< ProjectedPair< TQueried, TResult > > > projection)
Resolve the Projectable<TQueried, TResult>.
readonly CancellationToken cancellationToken
CancellationToken for the operation.
readonly Func< ProjectedPair< object?, TResult >?, AuthorityResponse< TResult > > resultMapper
Mapper for transforming the ProjectedPair<TQueried, TResult> TResult into an AuthorityResponse<TResu...
static Expression< Func< ProjectedPair< TQueried, TResult >, CombinedProjection > > CombinedProjectionExpression(Expression< Func< ProjectedPair< TQueried, TResult >, ProjectedPair< object?, TResult > > > selector)
Create an Expression<TDelegate> to transform a ProjectedPair<TQueried, TResult> into a CombinedProjec...
static Projectable< TQueried, TResult > Create< TSelection >(IQueryable< TQueried > query, Expression< Func< ProjectedPair< TQueried, TResult >, ProjectedPair< TSelection, TResult > > > selector, Func< ProjectedPair< TSelection, TResult >?, AuthorityResponse< TResult > > resultMapper, CancellationToken cancellationToken)
Create a Projectable<TQueried, TResult>.
static async ValueTask< Dictionary< long, AuthorityResponse< TResult > > > Combine(Func< IQueryable< TQueried >, IQueryable< ProjectedPair< TQueried, TResult > > > projection, params Projectable< TQueried, TResult >[] inputs)
Combine a set of Projectable<TQueried, TResult>s into the resulting AuthorityResponse<TResult>s.
Projectable(IQueryable< TQueried > query, Expression< Func< ProjectedPair< TQueried, TResult >, ProjectedPair< object?, TResult > > > selector, Func< ProjectedPair< object?, TResult >?, AuthorityResponse< TResult > > resultMapper, CancellationToken cancellationToken)
Initializes a new instance of the Projectable<TQueried, TResult> class.
static Projectable< TQueried, TResult > Create(IQueryable< TQueried > query, Func< ProjectedPair< object?, TResult >?, AuthorityResponse< TResult > > resultMapper, CancellationToken cancellationToken)
Create a Projectable<TQueried, TResult>.
readonly IQueryable< TQueried > query
The underlying IQueryable<T>. Should only select one entity.
DTO for moving database projected objects through the system.
required TResult Result
The output DTO TResult .
required TQueried Queried
The originally queried TQueried .