VOOZH about

URL: https://deepwiki.com/npgsql/efcore.pg/3.3-value-conversion

⇱ Value Conversion | npgsql/efcore.pg | DeepWiki


Loading...
Menu

Value Conversion

Purpose and Scope

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

Overview

Value conversion in the Npgsql provider serves two primary purposes:

  1. Collection Type Conversion: Transforming between different collection representations (e.g., List<int>int[], HashSet<T>T[]) to match PostgreSQL's array storage requirements src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs126-162
  2. Element Type Conversion: Converting element types within collections when the element itself requires transformation (e.g., LTree[]string[], enum[]int[]) src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs109-123

The 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 Architecture

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 ParameterPurpose
TModelCollectionThe collection type exposed in the EF Core model (may be an interface like IList<T>)
TConcreteModelCollectionThe concrete collection type to instantiate (e.g., List<T>, T[])
TProviderCollectionThe 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:

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

Converter Creation and Integration

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

Converter Creation Logic

The type mapping creates converters in the following scenarios:

  1. Element Converter Present: When the element type mapping has its own converter (e.g., LTree to string), an NpgsqlArrayConverter is instantiated that wraps the element converter src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs109-123
  2. Collection Type Mismatch: When TCollection 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-129

Sources: src/EFCore.PG/Storage/Internal/Mapping/NpgsqlArrayTypeMapping.cs100-130

Element-Level Conversion

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.

JSON Mapping and Conversion

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

Sources: src/EFCore.PG/Storage/Internal/Mapping/NpgsqlJsonTypeMapping.cs1-134

Collection Type Conversion

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

Parameter Binding and Materialization

During query execution, the provider applies conversions at two points:

1. Parameter Binding

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

2. Result Materialization

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

Conversion Expression Generation

The NpgsqlArrayConverter uses expression trees to generate efficient conversion code.

Indexable Strategy (Arrays/Lists)

For types supporting indexing, it uses a standard for loop src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs129-132

Enumerable Strategy (ICollection)

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

Nullable Element Handling

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: