Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/Marten/Linq/Parsing/Methods/MemoryExtensionsContains.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#nullable enable
using System;
using System.Collections;
using System.Linq;
using System.Linq.Expressions;
using Marten.Exceptions;
using Marten.Linq.Members;
using Marten.Linq.QueryHandlers;
using Weasel.Postgresql;
using Weasel.Postgresql.SqlGeneration;

namespace Marten.Linq.Parsing.Methods;
Expand All @@ -30,6 +33,31 @@ public ISqlFragment Parse(IQueryableMemberCollection memberCollection, IReadOnly
{
// This is the constant.Contains(value) pattern
var collectionMember = memberCollection.MemberFor(expression.Arguments[1]);

// #4610 mirror: on net10.0 the C# compiler resolves `array.Contains(x)` to
// MemoryExtensions.Contains (via the implicit array → ReadOnlySpan conversion),
// routing the same shape that EnumerableContains handles on net9 through this
// parser instead. The enum case has the same Npgsql parameter-mapping problem
// (`Writing values of 'EnumType[]' is not supported for parameters having
// NpgsqlDbType '-2147483639'`) and the same fix: project the constant
// collection through EnumIsOneOfWhereFragment so it becomes a string[]/int[]
// with the right NpgsqlDbType for the active EnumStorage.
if (collectionMember.MemberType.IsEnum && constant.Value is not null)
{
// EnumIsOneOfWhereFragment requires a System.Array; for net10's
// ReadOnlySpan path the captured value is still the original array, but
// a hand-written List<EnumType>.Contains-via-MemoryExtensions shape
// could land here too, so guard the conversion the same way.
var arrayValue = constant.Value is Array
? constant.Value
: ((IEnumerable)constant.Value).Cast<object>().ToArray();

return new EnumIsOneOfWhereFragment(
arrayValue,
options.Serializer().EnumStorage,
collectionMember.TypedLocator);
}

return new IsOneOfFilter(collectionMember, new CommandParameter(constant.Value));
}

Expand Down
Loading