Skip to content
FlexQuery.NET

Configuration

FlexQuery is configured at three levels, and every level has one job: the more general one supplies defaults, the more specific one overrides them. Understanding this layering — and the immutability rule that guards it — is the difference between predictable behavior and order-of-initialization bugs.

Plain text
Global (FlexQueryCore)          <- application-wide defaults, set once
  |- Provider (EFCore/Dapper)   <- provider behavior (no-tracking, model, timeout)
       `- Per request           <- per-call overrides (governance, limits, syntax)

Global options

FlexQueryCore.Configure runs once at startup, before any query:

C#
using FlexQuery.NET;

var builder = WebApplication.CreateBuilder(args);

FlexQueryCore.Configure(options =>
{
    options.DefaultQuerySyntax = QuerySyntax.NativeDsl;
    options.DefaultPageSize = 20;
    options.MaxPageSize = 1000;
    options.IncludeTotalCount = true;
    options.StrictFieldValidation = true;
    options.MaxFieldDepth = 5;
});
PropertyTypeDefaultDescription
DefaultQuerySyntaxQuerySyntaxNativeDslSyntax used when no per-request syntax is supplied.
DefaultPageSizeint20Page size when the client omits one.
MaxPageSizeint1000Maximum page size a client may request.
IncludeTotalCountbooltrueCompute total counts by default.
StrictFieldValidationbooltrueThrow on unauthorized field access.
MaxFieldDepthint5Maximum nested field-path depth.

Global type maps

FlexQueryOptions.CreateMap registers application-level entity to DTO maps that every typed execution reuses:

C#
FlexQueryCore.Configure(options =>
{
    options.CreateMap<Customer, CustomerResponse>()
        .ForMember(dto => dto.CustomerFullName, entity => entity.CustomerName);

    options.CreateMap<Order, OrderResponse>();
});

Per-query CreateMap registrations take precedence over global maps. See Typed DTO Projection.

Provider options

EF Core

C#
FlexQueryEFCore.Configure(options =>
{
    options.UseNoTracking = true;
});

FlexQueryEFCore.Setup() (no delegate) only registers the EF Core-specific operator handlers, such as like. UseNoTracking defaults execution to no-tracking; each call can override it (opt.UseNoTracking = false).

Dapper

Dapper needs a model — there is no DbContext to reflect over:

C#
using FlexQuery.NET.Dapper.Configuration;

FlexQueryDapper.Configure(options =>
{
    options.CommandTimeout = 30;

    options.Model.Entity<Customer>()
        .ToTable("Customers")
        .HasKey(c => c.Id)
        .HasMany(c => c.Orders)
        .HasForeignKey("CustomerId");
});

Relationship configuration can also be grouped per entity in an IEntityTypeConfiguration<T> class and applied with ApplyConfiguration / ApplyConfigurationsFromAssembly. Entity types with standard naming and [Table]/[Column]/[Key] attributes need no explicit configuration at all — conventions fill in the gaps.

The SQL dialect is auto-detected from the DbConnection type at runtime. See Dapper for the full mapping API.

Per-request overrides

Every execution method accepts an optional Action<...Options> delegate that wins over global/provider values:

C#
var result = await db.Customers
    .FlexQueryAsync(parameters, opt =>
    {
        opt.MaxPageSize = 50;                              // tighter ceiling
        opt.AllowedFields = ["Id", "FirstName", "Email"];  // endpoint surface
        opt.QuerySyntax = QuerySyntax.Fql;                 // force a syntax
        opt.UseNoTracking = false;                         // opt out of no-tracking (EF)
    }, cancellationToken);

Typical per-request settings: governance sets (see Security), paging limits, query syntax, field mappings, per-query type maps, and the diagnostics listener.

Precedence rules

SettingGlobalProviderPer request
Default query syntaxYesYes (overrides global)
Page size defaults / limitsYesYes (overrides global)
Validation strictness & field depthYes (baseline)Yes (overrides)
Field governance sets (Allowed/Blocked/…)Yes (per request)
No-tracking behaviorYes (default)Yes (per call)
Dapper model (statics/FlexQueryDapper.Configure)Yesattributes per query
Type mapsYes (global maps via FlexQueryOptions.CreateMap)Yes (per-query wins)

Common mistakes