# Supported Types and their Mappings

The following lists the built-in mappings when reading and writing CLR types to PostgreSQL types.

Note that in addition to the below, enum and composite mappings are documented in a separate page. Note also that several plugins exist to add support for more mappings (e.g. spatial support for PostGIS), these are listed in the Types menu.

## Read mappings

The following shows the mappings used when reading values.

- The default type is returned when using `NpgsqlCommand.ExecuteScalar()`, `NpgsqlDataReader.GetValue()` and similar methods.
- You can read as other types by calling `NpgsqlDataReader.GetFieldValue<T>()`.

PostgreSQL type | Default .NET type | Non-default .NET types
--- | --- | ---
boolean | bool |
smallint | short | byte, sbyte, int, long, float, double, decimal
integer | int | byte, short, long, float, double, decimal
bigint | long | long, byte, short, int, float, double, decimal
real | float | double
double precision | double |
numeric | decimal | byte, short, int, long, float, double, BigInteger (6.0+)
money | decimal |
text | string | char[], byte[]1
character varying | string | char[], byte[]1
character | string | char[], byte[]1
citext | string | char[], byte[]1
json | string | char[], byte[]1
jsonb | string | char[], byte[]1
xml | string | char[], byte[]1
uuid | Guid |
bytea | byte[]1 |
timestamp without time zone | DateTime (Unspecified) |
timestamp with time zone | DateTime (Utc2) | DateTimeOffset (Offset=0)2
date | DateTime | DateOnly (6.0+)
time without time zone | TimeSpan | TimeOnly (6.0+)
time with time zone | DateTimeOffset |
interval | TimeSpan3 | NpgsqlInterval
cidr | NpgsqlCidr4 |
inet | IPAddress | NpgsqlInet
macaddr | PhysicalAddress |
tsquery | NpgsqlTsQuery |
tsvector | NpgsqlTsVector |
bit(1) | bool | BitArray
bit(n) | BitArray |
bit varying | BitArray |
point | NpgsqlPoint |
lseg | NpgsqlLSeg |
path | NpgsqlPath |
polygon | NpgsqlPolygon |
line | NpgsqlLine |
circle | NpgsqlCircle |
box | NpgsqlBox |
cube | NpgsqlCube5 |
hstore | Dictionary<string, string> |
oid | uint |
xid | uint |
cid | uint |
oidvector | uint[] |
name | string | char[]
(internal) char | char | byte, short, int, long
geometry (PostGIS) | PostgisGeometry |
record | object[] |
composite types | T |
range types | NpgsqlRange<TElement> |
multirange types (PG14) | NpgsqlRange<TElement>[] |
enum types | TEnum |
array types | Array (of element type) |

1Types which can be read as `byte[]` can also be written as `ReadOnlyMemory<byte>` and `Stream`, and if they could be big, consider using `CommandBehavior.SequentialAccess` and `NpgsqlDataReader.GetStream()` to stream the row and column instead of buffering them. Note that if you're reading string data (e.g. `jsonb`) as binary, it's your responsibility to perform UTF8 decoding (or whatever encoding is configured for your database).

2 In versions prior to 6.0 (or when `Npgsql.EnableLegacyTimestampBehavior` is enabled), reading a `timestamp with time zone` returns a Local DateTime instead of Utc, and reading it as a DateTimeOffset returns a local offset based on the timezone of the server where Npgsql is running. See the breaking change note for more info.

3 PostgreSQL intervals with month or year components cannot be read as `TimeSpan`. Consider using NodaTime's Period type, or NpgsqlInterval.

4 Prior to version 8.0, the default mapping for `cidr` was `ValueTuple<IPAddress, int>`.

5 Introduced in Npgsql 10.0.0. Requires the PostgreSQL `cube` extension.

## Write mappings

There are three rules that determine the PostgreSQL type sent for a parameter:

1. If the parameter's `NpgsqlDbType` is set, it is used.
2. If the parameter's `DataType` is set, it is used.
3. If the parameter's `DbType` is set, it is used.
4. If none of the above is set, the backend type will be inferred from the CLR value type.

PostgreSQL type | Default .NET types | Non-default .NET types | NpgsqlDbType | DbType
--- | --- | --- | --- | ---
boolean | bool |  | Boolean | Boolean
smallint | short, byte, sbyte |  | Smallint | Int16
integer | int |  | Integer | Int32
bigint | long |  | Bigint | Int64
real | float |  | Real | Single
double precision | double |  | Double | Double
numeric | decimal, BigInteger (6.0+) |  | Numeric | Decimal, VarNumeric
money |  | decimal | Money | Currency
text | string, char[], char | byte[], ReadOnlyMemory<byte> | Text | String, StringFixedLength, AnsiString, AnsiStringFixedLength
character varying |  | string, char[], char, byte[]3 | Varchar |
character |  | string, char[], char, byte[]3 | Char |
citext |  | string, char[], char, byte[]3 | Citext |
json |  | string, char[], char, byte[]3 | Json |
jsonb |  | string, char[], char, byte[]3 | Jsonb |
xml |  | string, char[], char, byte[]3 | Xml |
uuid | Guid |  | Uuid |
bytea | byte[] | ArraySegment<byte>, Stream (7.0+) | Bytea | Binary
timestamp with time zone | DateTime (Utc)1, DateTimeOffset |  | TimestampTz | DateTime2, DateTimeOffset
timestamp without time zone | DateTime (Local/Unspecified)1 |  | Timestamp | DateTime2
date | DateOnly (6.0+) | DateTime | Date | Date
time without time zone | TimeOnly (6.0+) | TimeSpan | Time | Time
time with time zone |  | DateTimeOffset | TimeTz |
interval | TimeSpan | NpgsqlInterval | Interval |
cidr |  | ValueTuple<IPAddress, int>, IPAddress | Cidr |
inet | IPAddress | ValueTuple<IPAddress, int> | Inet |
macaddr | PhysicalAddress |  | MacAddr |
tsquery | NpgsqlTsQuery |  | TsQuery |
tsvector | NpgsqlTsVector |  | TsVector |
bit |  | bool, BitArray, string | Bit |
bit varying | BitArray | bool, BitArray, string | Varbit |
point | NpgsqlPoint |  | Point |
lseg | NpgsqlLSeg |  | LSeg |
path | NpgsqlPath |  | Path |
polygon | NpgsqlPolygon |  | Polygon |
line | NpgsqlLine |  | Line |
circle | NpgsqlCircle |  | Circle |
box | NpgsqlBox |  | Box |
cube | NpgsqlCube4 |  | Cube |
hstore | IDictionary<string, string> |  | Hstore |
oid |  | uint | Oid |
xid |  | uint | Xid |
cid |  | uint | Cid |
oidvector |  | uint[] | Oidvector |
name |  | string, char[], char | Name |
(internal) char |  | byte | InternalChar |
composite types | Pre-mapped type |  | Composite |
range types | NpgsqlRange<TSubtype> |  | Range | NpgsqlDbType |
enum types | Pre-mapped type |  | Enum |
array types | T[], List<T> |  | Array | NpgsqlDbType |

1 UTC DateTime is written as `timestamp with time zone`, Local/Unspecified DateTimes are written as `timestamp without time zone`. In versions prior to 6.0 (or when `Npgsql.EnableLegacyTimestampBehavior` is enabled), DateTime is always written as `timestamp without time zone`.

2In versions prior to 6.0 (or when `Npgsql.EnableLegacyTimestampBehavior` is enabled), `DbType.DateTime` is mapped to `timestamp without time zone`.

3Types which can be read as `byte[]` can also be written as `ReadOnlyMemory<byte>` and `Stream`.

4 Introduced in Npgsql 10.0.0. Requires the PostgreSQL `cube` extension.

Notes when using Range and Array, bitwise-or NpgsqlDbType.Range or NpgsqlDbType.Array with the child type. For example, to construct the NpgsqlDbType for a `int4range`, write `NpgsqlDbType.Range | NpgsqlDbType.Integer`. To construct the NpgsqlDbType for an `int[]`, write `NpgsqlDbType.Array | NpgsqlDbType.Integer`.

For information about enums, see the Enums and Composites page.