Repository: dotnet/efcore
File: src/EFCore.SqlServer/Query/Internal/SqlServerTypeMappingPostprocessor.cs (C#)

Code before:
            if (parameterTypeMapping is not SqlServerStringTypeMapping { ElementTypeMapping: not null })
            {
                throw new UnreachableException("A SqlServerStringTypeMapping collection type mapping could not be found");
            }

            return openJsonExpression.Update(
                parameterExpression.ApplyTypeMapping(parameterTypeMapping),
                path: null,
                [new SqlServerOpenJsonExpression.ColumnInfo("value", elementTypeMapping, [])]);
        }
        else
        {
            // We have no inferred type mapping for the element type. This means that there's was nothing in the query done
            // against the elements of the collection (e.g. comparison to a column), which tells us what type mapping it is.
            // In normal circumstances, such an expression would get client-evaluated in the funceltizer (no reference to a
            // column/database-side object), but with compiled queries the collection parameter gets preserved as-is.
            // The only thing we can do is apply the default type mapping.
            var parameterTypeMapping = RelationalDependencies.TypeMappingSource.FindMapping(parameterExpression.Type, QueryCompilationContext.Model);

            if (parameterTypeMapping is not { ElementTypeMapping: RelationalTypeMapping elementTypeMapping2 })
            {
                throw new UnreachableException("Default type mapping has no element type mapping");
            }

            return openJsonExpression.Update(
                parameterExpression.ApplyTypeMapping(parameterTypeMapping),
                path: null,
                [new SqlServerOpenJsonExpression.ColumnInfo("value", elementTypeMapping2, [])]);
        }
    }
}


Review comment (suggestion):
The code path at line 102 doesn't validate that the returned parameterTypeMapping has a non-null ElementTypeMapping before using it at line 110. The null check at lines 104-107 only validates that ElementTypeMapping is not null, but it doesn't throw or handle the case where parameterTypeMapping itself is null. This could result in a NullReferenceException. Consider adding a null check for parameterTypeMapping similar to the pattern used in lines 85-88.

Code after:
            parameterTypeMapping = _typeMappingSource.FindMapping(parameterExpression.Type, _model, elementTypeMapping);
        }
        else
        {
            // We have no inferred type mapping for the element type. This means that there was nothing in the query done
            // against the elements of the collection (e.g. comparison to a column), which tells us what type mapping it is.
            // In normal circumstances, such an expression would get client-evaluated in the funceltizer (no reference to a
            // column/database-side object), but with compiled queries the collection parameter gets preserved as-is.
            // The only thing we can do is apply the default type mapping.
            parameterTypeMapping = _typeMappingSource.FindMapping(parameterExpression.Type, QueryCompilationContext.Model);

            if (parameterTypeMapping is not { ElementTypeMapping: RelationalTypeMapping e })
            {
                throw new UnreachableException("Default type mapping has no element type mapping");
            }

            elementTypeMapping = e;
        }

        if (parameterTypeMapping is not SqlServerStringTypeMapping { ElementTypeMapping: not null })
        {
            throw new UnreachableException("A SqlServerStringTypeMapping collection type mapping could not be found");
        }

        return openJsonExpression.Update(
            parameterExpression.ApplyTypeMapping(parameterTypeMapping),
            path: null,
            [new SqlServerOpenJsonExpression.ColumnInfo("value", elementTypeMapping, [])]);
    }
}