From cc3eb8efb604f3cc5f2c365c7a31ff059c3df68a Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Sat, 14 Jun 2025 17:47:34 +0200 Subject: [PATCH] Make NpgsqlArrayConverter not throw for struct arrays Fixes #3551 --- .../ValueConversion/NpgsqlArrayConverter.cs | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs b/src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs index 982d58eaa..b4eda1bad 100644 --- a/src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs +++ b/src/EFCore.PG/Storage/ValueConversion/NpgsqlArrayConverter.cs @@ -185,11 +185,13 @@ private static Expression> ArrayConversionExpression NewArrayBounds(outputElementType, lengthVariable), + var t when typeof(TConcreteOutput).GetConstructor([typeof(int)]) is ConstructorInfo ctorWithLength => New(ctorWithLength, lengthVariable), + _ => New(typeof(TConcreteOutput)) + }) ]); if (indexer is not null) @@ -285,13 +287,21 @@ elementConversionExpression is null // return output; expressions.Add(output); - return Lambda>( - // First, check if the given array value is null and return null immediately if so - Condition( - ReferenceEqual(input, Constant(null)), - Constant(null, typeof(TOutput)), - Block(typeof(TOutput), variables, expressions)), - input); + Expression body = Block(typeof(TOutput), variables, expressions); + + // If the input type is a reference type, first check if the input array is null and return null + // (or default for output value type) if so, bypassing all of the logic above. + if (!typeof(TInput).IsValueType) + { + body = Condition( + ReferenceEqual(input, Constant(null, typeof(TInput))), + typeof(TOutput).IsValueType + ? New(typeof(TConcreteOutput)) + : Constant(null, typeof(TOutput)), + body); + } + + return Lambda>(body, input); } private static Expression ForLoop(