Repository navigation
Fix Contains on an object collection over a value-converted column - #3961
sanjaysingh wants to merge 2 commits into
Conversation
roji
left a comment
There was a problem hiding this comment.
Recommendation: keep the direction, but revise before merging. The reported scenario works with this PR, but manual validation found two ordinary variants that still fail; see the inline comments.
Problem
#3916 is a genuine provider bug. Given an int property converted to long, a typed collection works but an object-typed collection fails while building the array converter:
modelBuilder.Entity<Blog>().Property(b => b.Id)
.HasConversion(v => (long)v, v => checked((int)v));
object[] ids = [1, 2];
await context.Blogs.Where(b => ids.Contains(b.Id)).ToListAsync();Expected approach
Adapt the element converter's argument and result types once, before constructing null handling and either collection loop; allow object as the wider model element type; adapt the collection comparer and JSON reader consistently. This should remain a small PostgreSQL-provider change with focused regression coverage, not a new abstraction or broader EF change. No documentation change is needed for this bug fix.
Assessment
The comparer composition and JSON mapping changes are relevant, and retaining rejection of unrelated model-element types is good. The new unit tests check both conversion directions, and the functional tests verify actual results and ANY SQL for arrays and lists. However, four loop-site calls plus the new conversion helper are less direct than normalizing the element lambda centrally. Main already has that centralized normalization, so I would reuse it rather than add another conversion layer and a one-use matching helper.
Gaps
- String-backed converters still throw during construction. Changing the example's converter to
v => v.ToString(), v => int.Parse(v)reproduces the originalobject/intexpression error with both object arrays and lists. Astring-to-stringconverter fails similarly. The existing nullable-wrapper code invokes the incompatible lambda before the new helper is reached. - Null elements fail at parameter conversion. Keeping the original
int-to-longconverter but changing the input toobject[] ids = [null!, 2]throwsNullReferenceException;List<object>does too. An unconverted integer column handles that input, and a typed nullable collection handles a converted nullable property correctly. The widened input needs a null-preserving provider representation, not unconditional unboxing intointand storage inlong[].
These are incomplete parts of the proposed object-collection support, not demonstrated regressions in previously working typed-collection queries. Add focused string-provider and null-element cases rather than substantially expanding the test infrastructure; the existing primitive-collection fixture already has converted-element query tests.
Manual validation
I built exact commit afbe3ef648b6659cc4930aa12d9f3f84676fa2bc with its pinned .NET 11 SDK and ran a separate console application against PostgreSQL 18.4. Both reported int-to-long queries returned IDs 1,2 through ANY. The string-backed and null-element failures above were reproduced through the actual provider API, including query execution for the successful cases and null controls. All seven converter tests, both new PostgreSQL tests, and the existing HashSet/Dictionary-values converter tests also passed, which demonstrates the coverage gaps rather than a failure of the supplied tests.
Posted by copilot
…ns can compile. An object[] or List<object> was passed straight into an int converter, so the query failed to compile.
…-type element converter.
afbe3ef to
68beb15
Compare
|
Rebased onto main and removed the per-loop conversion helper. The element lambda is already normalized before the null wrapper, so an object collection with a string converter now builds. A null in that collection is preserved by using a nullable provider element. An int-to-long converter stores the value in long?[] instead of unboxing it into long[]. Typed collections still use ToNullableComparer. Added tests for a string converter and for null elements, including a match on a nullable converted property. The existing nullable-struct Contains test still passes. |
Containson anobject[]orList<object>failed to compile when the column had a value converter. The collection element isobject, but the converter expects the underlying type, such asint. Each element is now cast into the converter and back out, andobjectis accepted as that wider model element type.Fixes #3916
Test plan
object[]andList<object>, and for still rejecting a real type mismatch= ANY