Skip to content

fix(filter)!: use a constant for a TimeOnly value on net6.0 - #140

Merged
pdevito3 merged 1 commit into
v2from
fm/qk-breaking-timeonly-net6
Oct 2, 2026
Merged

pdevito3 merged 1 commit into
v2from
fm/qk-breaking-timeonly-net6

Conversation

@pdevito3

@pdevito3 pdevito3 commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner

For later consideration in a major version. Do not merge now. #134 restored the v1.14.2 behavior to keep v1.x compatible (restore commit 7653edb). This PR re-applies the net6.0 part of 5db8c4b (#110). The captain decides on this PR separately.

Summary

-    private static Expression NewTimeOnly(TimeOnly time)
+    private static Expression? NewTimeOnly(TimeOnly time)
     {
-        var ctor = typeof(TimeOnly).GetConstructor(new[] { typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) })!;
+        var ctor = typeof(TimeOnly).GetConstructor(new[] { typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) });
+        if (ctor == null)
+        {
+            return null;
+        }

When the constructor does not exist, FilterValue.Literal uses Expression.Constant for the value.

v1.14.2 behavior (and main)

QueryKit builds a TimeOnly value with new TimeOnly(int, int, int, int, int). This constructor (with microseconds) came in .NET 7. On net6.0 the lookup returns null, and Expression.New throws ArgumentNullException. Every filter with a TimeOnly value fails on net6.0. The opt-in ParameterizeFilterValues path does not use this code.

New behavior

On net6.0, the value is a constant TimeOnly. On net7.0 and later, nothing changes.

Example

// net6.0
FilterParser.ParseFilter<TestingPerson>("""Time == "08:30:00" """);
  • v1.14.2 and main: throws ArgumentNullException.
  • This PR: the filter compares x.Time with a constant TimeOnly value of 08:30:00.

Justification

QueryKit targets net6.0, but a TimeOnly filter does not work there. A constant value is correct for in-memory queries and for EF Core.

Migration

None. A net6.0 caller that caught ArgumentNullException for a TimeOnly filter now gets results.

README

No change.

Tests

PR 134 changed no test for this item. The test projects run only on net10.0, and this machine has no net6.0 runtime, so no test can run the net6.0 path. dotnet build -f net6.0 of the library has 0 warnings and 0 errors.

dotnet test: 470 unit tests and 297 Postgres integration tests (Testcontainers) pass, 0 failures.

Rebase on main

This branch is rebased on current main (#169). The rebase had no conflicts. The breaking change did not change.

@pdevito3
pdevito3 force-pushed the fm/qk-breaking-timeonly-net6 branch from 297c9f2 to 97cd716 Compare October 1, 2026 21:47
The TimeOnly constructor with five ints needs .NET 7. On net6.0, a filter with a TimeOnly value threw ArgumentNullException, because the constructor lookup returned null. Use a constant for the value when the constructor does not exist.

BREAKING CHANGE: on net6.0, a filter with a TimeOnly value no longer throws ArgumentNullException. It compares with a constant TimeOnly value.
@pdevito3
pdevito3 force-pushed the fm/qk-breaking-timeonly-net6 branch from 97cd716 to 9cfc4dc Compare October 2, 2026 19:43
@pdevito3
pdevito3 changed the base branch from main to v2 October 2, 2026 19:43
@pdevito3
pdevito3 merged commit 5c620ae into v2 Oct 2, 2026
2 checks passed
@pdevito3
pdevito3 deleted the fm/qk-breaking-timeonly-net6 branch October 2, 2026 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant