![]() |
VOOZH | about |
This page documents how PostgreSQL array and multirange types map to .NET collection types in the Npgsql EF Core provider. It covers the NpgsqlArrayTypeMapping class, collection type conversions via NpgsqlArrayConverter, and multirange support for PostgreSQL 14+.
Scope: This page focuses on the mechanics of array and collection type mappings. For information about querying arrays and using array operators in LINQ, see Collection Queries. For general type mapping concepts, see Type Mapping System. For value conversion patterns, see Value Conversion.
PostgreSQL supports native array types for any data type. An array type is denoted by appending [] to the element type name (e.g., integer[], text[], uuid[]). Arrays can be multidimensional and support various operators and functions specific to array manipulation.
The Npgsql provider maps PostgreSQL arrays to .NET collection types, supporting:
T[], including multidimensional arrays like int[,]. src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs132-133List<T>. test/EFCore.PG.Tests/Storage/NpgsqlTypeMappingSourceTest.cs17-19IEnumerable<T> with an appropriate constructor. src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs12-14Key characteristics:
Sources: src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs12-18 src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs539-651
The following diagram shows how collection type mappings are resolved from CLR types or store types within NpgsqlTypeMappingSource:
Sources: src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs539-651 src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs604-644
The NpgsqlArrayTypeMapping class is responsible for mapping PostgreSQL array types to .NET collections. It is a generic class with three type parameters:
| Parameter | Description | Example |
|---|---|---|
TCollection | The CLR type exposed to the model | List<int>, int[], IEnumerable<string> |
TConcreteCollection | The concrete instantiable type | List<int>, int[], List<string> |
TElement | The element type | int, string, MyEnum |
The distinction between TCollection and TConcreteCollection allows the mapping to handle abstract types like IEnumerable<T> while knowing which concrete type to instantiate when materializing query results. src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs59-60
Sources: src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs59-98
When creating an array type mapping, the provider must determine the appropriate concrete collection type to instantiate. This is handled by the FindCollectionMapping method. src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs539
Sources: src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs572-651 src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs100-171
Array type mappings are built on top of element type mappings. The array mapping delegates element-level operations to the element mapping. src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs37-50
When generating SQL literals for arrays, each element is converted using ElementTypeMapping.GenerateProviderValueSqlLiteral(). src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs313
Sources: src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs288-322
The NpgsqlArrayConverter class handles conversions between different collection types and applies element-level conversions. src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs10-15
The converter is instantiated when the element mapping has a value converter. src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs109-123
Sources: src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs10-63 src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs100-129
The NpgsqlArrayConverter generates lambda expressions that perform the collection conversion at runtime using ArrayConversionExpression. src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs69
| Input Type | Can Get Length? | Can Index? | Strategy |
|---|---|---|---|
T[] | Yes (ArrayLength) | Yes | Efficient for loop with pre-allocated output src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs129-132 |
List<T> | Yes (Count) | Yes | Efficient for loop with pre-allocated output src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs150-153 |
ICollection<T> | Yes (Count) | No | Enumerator-based loop with pre-allocated output src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs135-149 |
IEnumerable<T> | No | No | Call ToList() first, then process src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs162-167 |
Sources: src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs69-313
PostgreSQL 14 introduced multirange types. The provider automatically maps collections of ranges to multiranges when _supportsMultiranges is true. src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs62 src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs604-610
Sources: src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs62 src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs604-644
Array type mappings generate SQL literals in the PostgreSQL array literal syntax: ARRAY[element1, element2, ...]::element_type[]. src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs313-321
The implementation iterates through the collection and delegates element literal generation to the element type mapping:
Limitations: Multidimensional arrays (int[,]) are not supported for SQL literal generation and will throw NotSupportedException. src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs302-303
Sources: src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs288-322
When binding array parameters, the type mapping configures the NpgsqlParameter with the appropriate NpgsqlDbType. src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs238-243
Sources: src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs215-261 src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs330-342
Array type mappings automatically generate value comparers for collection equality and snapshot generation. src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs131-142
| Element Type | Comparer Type |
|---|---|
| Value type (non-nullable) | ListOfValueTypesComparer<TConcreteCollection, TElement> |
| Nullable value type | ListOfNullableValueTypesComparer<TConcreteCollection, TElement> |
| Reference type | ListOfReferenceTypesComparer<TConcreteCollection, TElement> |
Note: Multidimensional arrays currently do not have value comparers. src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs132-133
Sources: src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs132-142
When a store type ends with [], the provider parses it to resolve the array mapping. src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs654-662
| Store Type | Element Store Type | Element Size | Result |
|---|---|---|---|
varchar(32)[] | varchar(32) | 32 | Array of varchar(32) test/EFCore.PG.Tests/Storage/NpgsqlTypeMappingSourceTest.cs79-90 |
timestamp(5)[] | timestamp(5) | precision=5 | Array of timestamp(5) test/EFCore.PG.Tests/Storage/NpgsqlTypeMappingSourceTest.cs102-112 |
Sources: src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs654-693 test/EFCore.PG.Tests/Storage/NpgsqlTypeMappingSourceTest.cs76-90 test/EFCore.PG.Tests/Storage/NpgsqlTypeMappingSourceTest.cs102-112
Refresh this wiki