Skip to content

Supported Operators

This page is the authoritative reference for which LINQ operators translate to PartiQL server-side, which are evaluated client-side, and which are unsupported.

Filtering Operators

LINQ Operator PartiQL Translation Notes
Where WHERE Boolean properties normalized to = true
==, !=, scalar Equals =, <> Works on all scalar types; supports single-argument prop.Equals(value) and object.Equals(prop, value) for compatible scalar operands; complex property-to-property and parameter equality translate for map attributes; comparer and StringComparison overloads are unsupported
<, <=, >, >= <, <=, >, >= Numeric and date/time properties only; C# does not define these operators on string — use string.Compare or CompareTo instead
string.Compare(a, b) > 0 (any comparison against 0) a > b Required for string range comparisons; works with ==, !=, <, <=, >, >= against the literal 0
a.CompareTo(b) > 0 (any comparison against 0) a > b Same as above; 0 < a.CompareTo(b) form also supported (operands mirrored)
== null IS NULL OR IS MISSING Covers both DynamoDB null representations, including nested complex-property paths such as x.Profile.Address == null
!= null IS NOT NULL AND IS NOT MISSING De Morgan inverse of == null; also works on nested complex-property paths
EF.Functions.IsNull(prop) prop IS NULL Explicit: NULL type only
EF.Functions.IsNotNull(prop) prop IS NOT NULL Explicit: not NULL type
EF.Functions.IsMissing(prop) prop IS MISSING Explicit: attribute absent from item
EF.Functions.IsNotMissing(prop) prop IS NOT MISSING Explicit: attribute present
!expr NOT (expr) Operand always parenthesized
prop >= a && prop <= b prop BETWEEN a AND b Both bounds must be inclusive (>= and <=)
string.Contains(s) contains(attr, ?) Case-sensitive substring; no char/culture overloads
entity.Collection.Contains(value) contains(attr, ?) Native DynamoDB list/set primitive collection membership; scalar value-converted collections are not translated
string.StartsWith(s) begins_with(attr, ?) Case-sensitive prefix; no char/StringComparison overloads
collection.Contains(prop) prop IN [?, ...] In-memory collection membership; max 50 PK values, 100 non-key values

Projection Operators

LINQ Operator PartiQL Translation Notes
Select Explicit column list SELECT * is never emitted; computed expressions and nested complex-property shaping evaluate client-side

Ordering Operators

LINQ Operator PartiQL Translation Notes
OrderBy / OrderByDescending ORDER BY col ASC\|DESC Only partition key and sort key columns are valid
ThenBy / ThenByDescending Additional ORDER BY column For multi-partition queries, partition key must be the first column

Terminal Operators

Terminal operators execute the query and return results. The provider supports the following terminals:

LINQ Operator Behavior Notes
ToListAsync() Fetches all pages; returns List<T> Provider follows NextToken until exhausted
AsAsyncEnumerable() Streams results as IAsyncEnumerable<T> Marks the explicit client-side evaluation boundary; LINQ applied after this runs in-process
ToPageAsync(limit, token) Single DynamoDB request; returns DynamoPage<T> DynamoDB-specific; use for cursor-based pagination
First / FirstOrDefault Implicit Limit=1; single request Key-only safe path by default; AsUnsafeFilteredQuery() bypasses safety validation but can miss later matching items
Single / SingleOrDefault Implicit Limit=2; single request Key-condition-only; allows PK equality or PK IN; shared-table discriminator queries need base-table single-item lookup

Primary-Key Lookup

Use FindAsync when you have the full DynamoDB table key and want one entity by primary key. It checks the EF Core change tracker first. If the entity is not already tracked, the provider executes a base-table key-equality PartiQL query with ExecuteStatementRequest.Limit = 1.

// Partition-key-only table
var customer = await context.Customers.FindAsync(["CUSTOMER#123"], ct);

// Composite partition + sort key table; pass values in PK, SK order
var order = await context.Orders.FindAsync(["CUSTOMER#123", "ORDER#456"], ct);

FindAsync returns null when no item exists. It targets the base table and does not use secondary indexes or automatic index selection; use normal LINQ with .WithIndex(...) or automatic selection for secondary-index lookups. Synchronous Find can return an already-tracked entity, but throws if it needs to query DynamoDB.

DynamoDB-Specific Extensions

The following extension methods are unique to this provider and have no standard LINQ equivalent. They compose with the query before a terminal operator is called.

Extension Behavior Notes
Limit(n) Sets ExecuteStatementRequest.Limit — evaluation budget DynamoDB reads up to n items then applies filters; returned count is 0..n. Last call wins. See Ordering and Limiting
WithNextToken(token) Seeds the first request with a saved continuation cursor Resumes a previous query from a known position. See Pagination
WithConsistentRead() Requests strongly consistent reads for this query Sets ExecuteStatementRequest.ConsistentRead = true for base-table and LSI reads. Throws if the finalized source is a GSI because DynamoDB does not support strong consistency on GSIs. WithConsistentRead(false) explicitly uses eventually consistent reads for one query
WithIndex(name) Routes the query to a named GSI or LSI Emits FROM "Table"."Index" in PartiQL. See Index Selection
WithoutIndex() Forces base-table execution; suppresses automatic index selection Emits diagnostic DYNAMO_IDX006. Cannot combine with WithIndex(...)
AsUnsafeFilteredQuery() Bypasses First* safety validation for this query Does not disable scan-like query protection, does not bypass Single* validation, and does not change terminal execution semantics. Use only for tests or controlled legacy code

Unsupported Operators

The following operators are not supported and throw InvalidOperationException at translation time. The provider does not silently fall back to in-process evaluation.

Category Operators Reason
Element operators Any, All Not supported server-side; use AsAsyncEnumerable() then LINQ-to-objects
Offset / paging Skip, Take, ElementAt, ElementAtOrDefault DynamoDB has no offset semantics; use Limit(n) for evaluation budget
Reverse traversal Last, LastOrDefault, Reverse Requires reverse index traversal, not currently implemented
Deduplication Distinct SELECT DISTINCT is not supported in DynamoDB PartiQL
Aggregation Count, LongCount, Sum, Average, Min, Max No aggregate functions in DynamoDB PartiQL; use AsAsyncEnumerable() for in-memory aggregation
Grouping GroupBy GROUP BY is not supported
Joins Join, GroupJoin, SelectMany, LeftJoin, RightJoin, DefaultIfEmpty DynamoDB does not support cross-item joins
Set operations Union, Concat, Except, Intersect Not supported
Conditional filtering SkipWhile, TakeWhile Not supported
Type filtering OfType<T>, Cast<T> Not supported

Scalar Type Support

All scalar entity properties must map to a DynamoDB attribute type. Types without a native wire representation use built-in EF Core value converters.

.NET Type DynamoDB Attribute Type Wire Format
string S
bool BOOL
byte, sbyte, short, int, long N Numeric string
ushort, uint, ulong N Numeric string
float, double, decimal N Numeric string
byte[] B Binary
Guid S "D" format, e.g. "550e8400-e29b-41d4-a716-446655440000"
DateTime S ISO 8601 round-trip ("O")
DateTimeOffset S ISO 8601 round-trip ("O")
DateOnly S "yyyy-MM-dd", e.g. "2026-04-19"
TimeOnly S "HH:mm:ss" (whole-second) or "o" (sub-second)
TimeSpan S Constant ("c") format, e.g. "01:30:00"
Enum N Underlying numeric value (string names require a converter)

Nullable variants of all types above are supported. Numeric comparisons use DynamoDB's single N wire type, so promotions to int, such as short to int, still bind as DynamoDB numbers. Custom types can be mapped using EF Core value converters; query parameters and constants use the property mapping so converters apply consistently.

Value-converted enums compare using the converter provider type. For example, an enum mapped with .HasConversion<string>() binds parameters as DynamoDB strings. Numeric casts of value-converted enums, such as (int)entity.Status == value, are not translated for parameter comparisons because the DynamoDB attribute stores the converted provider value. Compare enum values directly, or map the enum numerically if numeric comparisons are required.

See also