Pular para o conteúdo principal
Versão: main (dev) 🚧

ITLab.Template.DevPack.Data

Defines repository and unit-of-work contracts, paginated and grouped query primitives, and utility discriminated types.

Componentes

TipoNomeResponsabilidade
InterfaceIRepository<T>Repository contract with CRUD operations and unit-of-work access
InterfaceIUnitOfWorkCommit boundary for persistence operations
EnumEOrderDirectionSort direction for ordered queries: asc, desc
Abstract ClassPaginatedQueryBaseBase class for paginated query requests (page, size, order, group, filter)
Abstract ClassPaginatedQueryBase<TDto>Typed variant implementing IQuery<PaginatedList<TDto>>
ClassPaginatedList<T>Paginated slice of query results with metadata (page, totalCount, hasPrev/Next)
ClassGroupableList<T>Paginated list with server-side grouping support
ClassGroup<T>Represents a grouped set of items with a composite key and item count
ClassGroupKeyImmutable composite key identifying a group (dictionary of field→value pairs)
StructOneOf<T0, T1>Lightweight discriminated union for dual-result scenarios
ClassOneOfEnumerable<T>OneOf alias carrying an IEnumerable<T> in one arm
ClassOneOfList<T>OneOf alias carrying an IList<T> in one arm
Static ClassOneOfFactory helpers for creating OneOf instances
Static ClassQueryFilterDSL parser that converts a filter string into an Expression<Func<T, bool>> compatible with EF Core and in-memory queries (DSL version 1.0.2)

Como usar

// Paginated query — products inherit PaginatedQueryBase<TDto>.
// PaginatedQueryBase<T> is an abstract CLASS — records cannot inherit from
// non-record base types in C# (CS8865/CS0115). Declare paginated queries
// as `class`, not `record`.
public sealed class ListOrdersQuery : PaginatedQueryBase<OrderDto>
{
}

// Repository usage in an application handler.
public async Task<Result> Handle(CreateCustomerCommand command)
{
_repository.Add(new Customer(command.Name));
await _repository.Commit();
return Result.Success();
}

// OneOf for a handler that returns either a list or a grouped list.
OneOf<PaginatedList<OrderDto>, GroupableList<OrderDto>> result = await mediator.Send(query);
result.Match(list => list.Items, grouped => grouped.Groups.SelectMany(g => g.Items));

// QueryFilter: parse a filter string from the request into a LINQ predicate.
var predicate = QueryFilter.ParseFilter<Order>("status eq 'Active' and total gt 100");
var orders = await dbContext.Orders.Where(predicate).ToListAsync();

The paginated-query declaration above — auto-suficiente, verificado pelo smoke check (regression do record : PaginatedQueryBase<T>):

public sealed record OrderDto(Guid Id, string Customer);

public sealed class ListOrdersQuery : PaginatedQueryBase<OrderDto>
{
}

O que não fazer

  • Do not expose ORM-specific APIs through IRepository<T> consumers.
  • Do not skip IUnitOfWork commit boundaries in write flows.
  • Do not add product-specific query properties to PaginatedQueryBase — derive from it instead.
  • Do not declare record : PaginatedQueryBase<T> — base é classe abstrata e records não herdam de classes não-record. Use class : PaginatedQueryBase<T>.

Extensão pelo produto

  • Products implement repositories with EF Core or other stores while preserving IRepository<T> semantics.
  • Products derive from PaginatedQueryBase<TDto> and add product-specific filter properties.
  • Products may adopt OneOfEnumerable / OneOfList aliases for flexible read-model payloads.
  • Para registrar endpoints sobre PaginatedQueryBase<TDto>, ver MapPaginatedGet em areas/Extensions/README.md (DevPack 10.3.0+) — encapsula o bind individual de pageNumber/pageSize/orderBy/order/filter/paginated.