![]() |
VOOZH | about |
This document covers the value conversion system in the Npgsql Entity Framework Core provider. Value conversion transforms data between the CLR types used in application models and the provider types sent to PostgreSQL. This page focuses specifically on how value converters are created, composed, and applied during parameter binding and result materialization, with particular emphasis on the NpgsqlArrayConverter and its role in handling PostgreSQL arrays.
For information about how CLR types are mapped to PostgreSQL types without conversion, see Built-in Type Mappings For array-specific type mapping behavior, see Array and Collection Mappings
Value conversion in the Npgsql provider serves two primary purposes:
List<int> ↔ int[], HashSet<T> ↔ T[]) to match PostgreSQL's array storage requirements src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs126-162LTree[] ↔ string[], enum[] ↔ int[]) src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs109-123The value conversion system operates at the intersection of EF Core's generic value conversion infrastructure and Npgsql's PostgreSQL-specific type mappings. Converters are instantiated and attached to type mappings during the mapping creation process.
Diagram: Value Conversion Flow for Collections
Sources: src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs10-40 src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs100-130
NpgsqlArrayConverter<TModelCollection, TConcreteModelCollection, TProviderCollection> is the core component for array value conversion src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs10-15 It accepts three type parameters:
| Type Parameter | Purpose |
|---|---|
TModelCollection | The collection type exposed in the EF Core model (may be an interface like IList<T>) |
TConcreteModelCollection | The concrete collection type to instantiate (e.g., List<T>, T[]) |
TProviderCollection | The provider collection type sent to Npgsql ADO.NET (typically T[]) |
The converter optionally wraps an element-level ValueConverter to transform individual elements during collection conversion src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs32-38
Diagram: NpgsqlArrayConverter Responsibilities
The converter generates lambda expressions at construction time to perform the conversions efficiently at runtime src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs69-71 The expression generation logic differs based on the input collection type:
for loop src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs129-132List<T> before processing src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs149-162Sources: src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs65-313
Value converters are created during type mapping construction. The process occurs in NpgsqlArrayTypeMapping<TCollection, TConcreteCollection, TElement>.CreateParameters src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs100
Diagram: Converter Creation Sequence
Sources: src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs100-130 src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs554-652
The type mapping creates converters in the following scenarios:
LTree to string), an NpgsqlArrayConverter is instantiated that wraps the element converter src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs109-123TCollection differs from TConcreteCollection (e.g., model uses IList<int> but concrete type is List<int>), a converter handles the collection type transformation without element conversion src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs124-129Sources: src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs100-130
When an element mapping has a converter, the array converter composes with it to provide nested conversion. This pattern is common for PostgreSQL-specific types like JSON or LTree.
The NpgsqlJsonTypeMapping handles conversion for JSON types src/EFCore.PG/Storage/Internal/Mapping/NpgsqlJsonTypeMapping.cs14 It supports mapping json/jsonb to string, JsonDocument, JsonElement, or arbitrary POCOs src/EFCore.PG/Storage/Internal/Mapping/NpgsqlJsonTypeMapping.cs88-114
JsonStringReaderWriter.Instance src/EFCore.PG/Storage/Internal/Mapping/NpgsqlJsonTypeMapping.cs35JsonSerializer during SQL literal generation src/EFCore.PG/Storage/Internal/Mapping/NpgsqlJsonTypeMapping.cs112Sources: src/EFCore.PG/Storage/Internal/Mapping/NpgsqlJsonTypeMapping.cs1-134
When no element conversion is required but collection types differ, the array converter handles pure collection type transformations. This is critical for supporting interfaces like IEnumerable<T> in queries.
Diagram: Collection Type Conversions
These conversions are necessary because Npgsql ADO.NET expects specific collection types (usually arrays) for parameter binding src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs222-240
Sources: src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs126-162 src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs215-240
During query execution, the provider applies conversions at two points:
Before sending a command to PostgreSQL, the provider converts model values to provider values. If a collection is passed that is not an array or List<T>, the provider materializes it src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs222-240
When reading data back from the database, the provider uses the ConvertFromProviderExpression generated by the converter to transform database values into the model's CLR types src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs37-38
Sources: src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs215-261 src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs33-39
The NpgsqlArrayConverter uses expression trees to generate efficient conversion code.
For types supporting indexing, it uses a standard for loop src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs129-132
For types like HashSet<T>, it uses the Count property for allocation and an enumerator for iteration src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs135-144
The converter automatically handles null-sanitization for nullable value types by wrapping the element conversion in a null check src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs87-106
Sources: src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs69-313
Page Sources:
Refresh this wiki