Linq.Expressions.Translation.PostgreSql
0.1.0-preview.0.2.0
dotnet add package Linq.Expressions.Translation.PostgreSql --version 0.1.0-preview.0.2.0
NuGet\Install-Package Linq.Expressions.Translation.PostgreSql -Version 0.1.0-preview.0.2.0
<PackageReference Include="Linq.Expressions.Translation.PostgreSql" Version="0.1.0-preview.0.2.0" />
<PackageVersion Include="Linq.Expressions.Translation.PostgreSql" Version="0.1.0-preview.0.2.0" />
<PackageReference Include="Linq.Expressions.Translation.PostgreSql" />
paket add Linq.Expressions.Translation.PostgreSql --version 0.1.0-preview.0.2.0
#r "nuget: Linq.Expressions.Translation.PostgreSql, 0.1.0-preview.0.2.0"
#:package Linq.Expressions.Translation.PostgreSql@0.1.0-preview.0.2.0
#addin nuget:?package=Linq.Expressions.Translation.PostgreSql&version=0.1.0-preview.0.2.0&prerelease
#tool nuget:?package=Linq.Expressions.Translation.PostgreSql&version=0.1.0-preview.0.2.0&prerelease
Linq.Expressions.Translation.PostgreSql
Translates the expression tree of an IQueryable<T> into a single PostgreSQL SELECT statement.
What is translated
Where,Select,OrderBy/OrderByDescending/ThenBy/ThenByDescending,Skip,Take,TakeLast,SkipLast,Distinct,Reverse,CastandOfType; an operator that cannot extend the currentSELECT(for exampleWhereafterTake) wraps it into a derived table.- Comparison, logical, arithmetic, bitwise and conditional operators,
??, conversions, string concatenation andNullable<T>members. stringmembers (Length, case conversion, trimming,Substring,Remove,IndexOf/LastIndexOf/IndexOfAny,Replace,Contains/StartsWith/EndsWithasLIKEwith escaped wildcards,IsNullOrEmpty,Concat,Formatand interpolated strings without alignment or format strings),Mathfunctions and theirint/long/decimal/doublecounterparts,double.IsNaN/IsInfinity/IsFinite, date and time parts and arithmetic (DateTime,DateTimeOffset,DateOnly,TimeOnly),DateTime.Now/UtcNow,DateTimeOffset.Now/UtcNow,Guid.NewGuid,Enum.HasFlagandToStringof numbers andGuid.Contains(andAny(x => x == value)) on in-memory collections (IN (...)) and on array columns (= ANY (...)), plus arrayLengthandCount().- Terminal operators:
Count/LongCount,Sum,Average,Min,Max,Any,All,Contains,First/Single/Last/ElementAt(and theirOrDefaultforms, which substitute the default of a value type inside a lambda), and aggregates afterDefaultIfEmpty(). - The same operators inside lambdas, as correlated or uncorrelated subqueries (
EXISTS,IN (SELECT ...), scalar subqueries). Join(INNER JOIN),GroupJoin(aggregated groups as correlated subqueries, also afterWhere,Select,OrderBy,Distinctor paging of the group, orLEFT JOINwithSelectMany/DefaultIfEmpty) andSelectMany(CROSS JOIN, correlatedINNER/LEFT JOIN, orJOIN LATERALwhen the inner source is paged).GroupBy(with element and result selectors):GROUP BYthe flattened key,HAVINGfor filters on groups, and aggregates over the group —Count(also with a predicate, asFILTER (WHERE ...)),Sum,Average,Min,Max,Any/All(BOOL_OR/BOOL_AND),Where(...)(possibly chained) before an aggregate andSelect(...).Distinct().Count()(COUNT(DISTINCT ...)).Concat,Union,IntersectandExceptasUNION ALL,UNION,INTERSECTandEXCEPT, parenthesizing operands that are paged or a different set operation.- Captured variables and parameter-free subtrees, which are evaluated in memory and rendered as literals.
Anything else — user-defined methods, culture- or comparison-specific overloads, navigation properties, in-memory sources, operators such as Zip, Aggregate or SkipWhile — throws NotSupportedException naming the offending member, method or expression node.
Overview
The package exposes exactly one public type, PostgreSqlQuery. It accepts a System.Linq.Expressions.Expression — the Expression of an IQueryable<T> — and exposes the PostgreSQL SELECT statement for that tree as its TextValue.
IQueryable<Order> orders = ...; // any IQueryable<T> whose provider builds the tree
string sql = new PostgreSqlQuery(
orders.Where(o => o.Total > 100).Select(o => o.Id).Expression
).TextValue;
// SELECT t0."Id" FROM "Order" AS t0 WHERE t0."Total" > 100
The package does not execute queries, open connections or materialize results; it only produces SQL text.
Mapping
A table is named after the element type and its columns after its public properties, in declaration order. [Table] (including its Schema), [Column] and [NotMapped] from System.ComponentModel.DataAnnotations.Schema override the defaults. Identifiers are always double-quoted, so their case is kept. A property whose type is not a scalar (or an array of scalars) is rejected, so navigation properties are not supported.
Nullability follows the CLR: Nullable<T> and nullable reference types are nullable columns. C# semantics are preserved where SQL differs — equality with a nullable operand uses IS [NOT] DISTINCT FROM, a nullable comparison used as a value becomes COALESCE(..., FALSE), nullable keys sort as NULLS FIRST ascending, membership tests (IN, = ANY) of a nullable value used as a value or under NOT become COALESCE(..., FALSE), and a nullable string or number is concatenated as COALESCE(..., ''). Concatenating a bool, an enum or a date or time value is rejected, as PostgreSQL formats them differently from .NET.
Constants are inline literals
The result is a single string, not a command with a parameter collection. Every constant in the tree — literals, captured variables and in-memory collections — is rendered as a safely escaped inline PostgreSQL literal (for example, 'O''Brien' for the string O'Brien). No bind parameters ($1, @p0) are produced.
Native AOT and trimming
The package is marked IsAotCompatible and builds without trimming or AOT warnings. Translation reads the public properties of the queried element types to find their columns, so TextValue is annotated [RequiresUnreferencedCode]: in a trimmed or Native AOT application a property that the code never references is removed, and its column silently disappears from SELECT. Keep the properties of every mapped type and then acknowledge the IL2026 warning at the call site, for example:
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(Order))]
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Order properties are preserved.")]
static string Sql(IQueryable<Order> orders)
{
return new PostgreSqlQuery(orders.Expression).TextValue;
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Linq.Expressions.Translation.PostgreSql:
| Package | Downloads |
|---|---|
|
Pure.RelationalSchema.Storage.PostgreSQL.Querying
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0-preview.0.2.0 | 55 | 10/16/2026 |
| 0.1.0-preview.0.1.0 | 50 | 10/15/2026 |