VOOZH about

URL: https://deepwiki.com/npgsql/efcore.pg/3.2-array-and-collection-mappings

⇱ Array and Collection Mappings | npgsql/efcore.pg | DeepWiki


Loading...
Menu

Array and Collection Mappings

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 Array Type System

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:

Key characteristics:

Sources: src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs12-18 src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs539-651


Collection Type Resolution Flow

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


NpgsqlArrayTypeMapping Architecture

The NpgsqlArrayTypeMapping class is responsible for mapping PostgreSQL array types to .NET collections. It is a generic class with three type parameters:


Generic Type Parameters

ParameterDescriptionExample
TCollectionThe CLR type exposed to the modelList<int>, int[], IEnumerable<string>
TConcreteCollectionThe concrete instantiable typeList<int>, int[], List<string>
TElementThe element typeint, 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


Type Parameter Instantiation Logic

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


Element Type Mapping Integration

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


Value Conversion for Collections

The NpgsqlArrayConverter class handles conversions between different collection types and applies element-level conversions. src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs10-15

Converter Architecture


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


Array Conversion Algorithm

The NpgsqlArrayConverter generates lambda expressions that perform the collection conversion at runtime using ArrayConversionExpression. src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs69

Input TypeCan Get Length?Can Index?Strategy
T[]Yes (ArrayLength)YesEfficient for loop with pre-allocated output src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs129-132
List<T>Yes (Count)YesEfficient for loop with pre-allocated output src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs150-153
ICollection<T>Yes (Count)NoEnumerator-based loop with pre-allocated output src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs135-149
IEnumerable<T>NoNoCall ToList() first, then process src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs162-167

Sources: src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs69-313


Multirange Support (PostgreSQL 14+)

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

Version-Dependent Behavior


Sources: src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs62 src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs604-644


SQL Literal Generation

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


Parameter Configuration

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


Value Comparers for Collections

Array type mappings automatically generate value comparers for collection equality and snapshot generation. src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs131-142

Element TypeComparer Type
Value type (non-nullable)ListOfValueTypesComparer<TConcreteCollection, TElement>
Nullable value typeListOfNullableValueTypesComparer<TConcreteCollection, TElement>
Reference typeListOfReferenceTypesComparer<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


Integration with Store Type Names

When a store type ends with [], the provider parses it to resolve the array mapping. src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs654-662

Store TypeElement Store TypeElement SizeResult
varchar(32)[]varchar(32)32Array of varchar(32) test/EFCore.PG.Tests/Storage/NpgsqlTypeMappingSourceTest.cs79-90
timestamp(5)[]timestamp(5)precision=5Array 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