These options are provided to a connection pool to use for every new connection needed.
| Option | Description | Default |
|---|---|---|
| Host | Host name/address of the database server | required |
| Port | Host port to connect to | 5432 |
| Username | User to connect with as | required |
| ApplicationName | application_name property set for each connection |
sqlx-cs-driver |
| Password | Password provided for the user connecting. This will become optional in the future if/when password-less connection are enabled for this driver (e.g. GSS-API, SSPI, OAuth tokens) | required |
| Database | Optional database name to initialize connections with. By default, Postgres will attempt to connect to a database with the same name as the username. | required |
| ConnectTimeout | Timeout to use when creating a new connection to the database. Must be postive and non-zero. Use Timeout.InfiniteTimeSpan to disable timeout |
15s |
| QueryTimeout | Timeout to use when executing a query(s) against the database. Must be postive and non-zero. Use Timeout.InfiniteTimeSpan to disable timeout. Currently this sets the statement_timeout connection property upon intialization so it's not currently configurable per query. |
Infinite |
| StatementCacheCapacity | Size of the prepared statement cache. Setting a larger size will allow for more. Setting a larger size will allow for more statements to be executed without parsing again, but it will accumulate more statements on the server side which could impact performance of the server. | 100 |
| UseExtendedProtocolForSimpleQueries | True if the driver should execute some simple statements as prepared queries. This does not impact simple statements that contain multiple queries or characters that look like parameter placeholders. This generally improves performance by using binary encoding for results but also might slow down performance. | true |
| SslMode | !CURRENTLY DOES NOTHING! SSL behaviour for connecting to databases that support SSL connection. | SslMode.Prefer |
| ExtraFloatPoints | This should rarely if ever be changed. Consulte docs for more details. | 1 |
| CurrentSchema | Default schema to use after connecting. Sets the search_path connection property of the connections. |
n/a |
| SslMode | !CURRENTLY DOES NOTHING! SASL-PLUS channel bidning behaviour for connecting to databases using SASL over an SSL connection. | ChannelBinding.Prefer |
| LoggerFactory | Logger creation factory of type Microsoft.Extensions.Logging.ILoggerFactory used by all objects that create loggers. |
Factory with console logger |
| CLR Type | Postgres Type |
|---|---|
| bool | BOOLEAN |
| sbyte | "CHAR" |
| short | SMALLINT |
| int | INTEGER |
| long | BIGINT |
| float | REAL |
| double | DOUBLE PRECISION |
| TimeOnly | TIME |
| DateOnly | DATE |
| DateTime | TIMESTAMP, TIMESTAMP WITH TIME ZONE |
| DateTimeOffset | TIMESTAMP WITH TIME ZONE, TIMESTAMP |
| DateOnly | DATE |
| decimal | NUMERIC(x, y) |
| byte[] | BYTEA |
| string | TEXT, VARCHAR(x), CHAR(x), NAME, BPCHAR, XML |
| Guid | UUID |
| IPNetwork | CIDR, INET |
| BitArray | VARBIT(x), BIT(x) |
| PgRange<long>* | INT8RANGE |
| PgRange<int>* | INT4RANGE |
| PgRange<DateOnly>* | DATERANGE |
| PgRange<DateTime>* | TSRANGE |
| PgRange<DateTimeOffset>* | TSTZRANGE |
| PgRange<decimal>* | NUMRANGE |
| PgBox* | BOX |
| PgCircle* | CIRCLE |
| PgInet* | INET, CIDR |
| PgInerval* | INTERVAL |
| PgLine* | LINE |
| PgLineSegment* | LSEG |
| PgMacAddress* | MACADDR |
| PgMacAddress8* | MACADDR8 |
| PgMoney* | MONEY |
| PgOid* | OID |
| PgPath* | PATH |
| PgPoint* | POINT |
| PgPolygon* | POLYGON |
| PgTimeTz* | TIME WITH TIME ZONE |
| T, JsonValue<T> | JSONB, JSON |
| Enum | ENUM |
| Enum | INTEGER |
| Enum | TEXT, VARCHAR(x) |
| T | COMPOSITE |
* Type custom to the sqlx-cs-pg library
All drivers implement a source generator for IFromRow. The Postgres driver supports deserializing
to any type that is found in the table above. It also supports a few attributes for custom
behaviour:
[PgPropertySkip]- Skip this property during deserialization[PgName(string)]- Use a custom name instead of translating the property name to a field name[FlattenField]- Defer to the field's type for deserialization, intended for nested type within the row[JsonField]- Treat the field value as JSON and deserialize into the field type, see notes below
Postgres supports unstructured data through the JSON and JSONB types. Extracting those field
types are handled with the IPgDataRow.GetField method where the parameter is JsonValue<T> and
T is the underlining type that the JSON represents. If you intend to source generate
JsonTypeInfo<T>, you can include those in the PgConnectOptions.JsonSerializerOptions.
All postgres types have an implicit array type created and can be extracted as a T[] using
IPgDataRow methods.
Note that array types are automatically mapped for custom enum and composite types created by a user when that type if mapped to a connection pool.
Enum types are natively supported by Postgres,
but sometimes you might also want a type that is easier to change then enum types (e.g. removing an
entry can be cumbersome). To accomidate this, sqlx-cs supports CLR enum types in 3 ways:
- Native Postgres enums. Just ensure that
IPgConnectionPool.MapEnumAsync<TEnum>when initializing the pool so that the database specific OID is collected.CREATE TYPE enum_type AS ENUM ('none', 'something');[PgEnum(Name = "enum_type", RenameAll = Rename.SnakeCase)] public enum EnumType { None, Something, }
- Int wrapper (simple cast of database
integervalue to an enum value)[WrapperEnum(Representation = EnumRepresentation.Int)] public enum IntEnum { None = 0, Something = 1, }
- Text wrapper (uses the enum label names to generate mapping to and from database
textvalue)[WrapperEnum(Representation = EnumRepresentation.Text)] public enum IntEnum { None, [PgName("something")] // Map to slightly different name/value Something, }
Postgres also natively supports composite types that can be declared as a new type with 1 or more attributes that are other postgres types. Note that this also applies to tables because postgres internally keeps track of table rows as composite types. This allows you to fetch other complete table rows as the composite and deserialize those rows (or arrays of rows) on the client rather than sending non-normalized data to the client and aggregating into the desired objects.
CREATE TYPE composite_type AS (
id integer,
"name" text,
title text
);
[PgComposite(Name = "composite_type", RenameAll = Rename.SnakeCase)]
public readonly partial struct CompositeType
{
public int Id { get; init; }
public string Name { get; init; }
public string? Title { get; init; }
}Just ensure that IPgConnectionPool.MapCompositeAsync<TComposite> when initializing the pool so
that the database specific OID is collected.
Copy statements are supported for
COPY FROM and COPY TO. To execute either statement you must create a ICopyStatment instance.
ICopyStatements provide all the features that a raw copy query provides but with some guardrails
to avoid issues (such as specifying the wrong value for options).
To interact with the copy API, there are 4 methods:
IPgConnection.CopyOutAsync=> writes the copy data to a provided streamIPgConnection.CopyOutRowsAsync=> transforms binary copy data to row type instancesIPgConnection.CopyInAsync=> copies a stream to the connection and returns aQueryResultwith the rows affectedIPgConnection.CopyInRowsAsync=> consumes a stream ofIPgBinaryCopyRowinstances as copy data and returns aQueryResultwith the rows affected
However, there are convenience methods that wrap these base methods to handle common use cases such as:
- Passing a file as the input data using a file path
- Writing output data to a file
PostgreSQL databases support a LISTEN/NOTIFY
protocol to subscribe to a desired channel and publish asynchronous messages to subscribers.
Although the IPgConnection instances can listen to channel and do receive notifications, they are
not set up to interact with them. There is another type IPgListener that uses a connection to
listen and receive notifications. To create a listener use IPgConnectionPool.CreateListener. Just
understand that this will remove a connection from the pool for the duration of the listener usage.
using IPgListener listener = pool.CreateListener();
await listener.ListenAsync("channel");
// Infinite loop until cancelled
await foreach (PgNotification notification in listener.ReceiveNotificationsAsync())
{
// handle notifcation
}