From 10cad1d1e494f6b35cadc7163e5a4f3c79cac9f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Na=CC=8Akkve=20Kierulf?= Date: Tue, 15 Sep 2026 08:51:25 +0200 Subject: [PATCH 1/2] fix: extend date-only Le filters to end of day A date-only value used with the Le operator against a DateTime property (e.g. filter[createdAt][le]=2026-09-14) parsed to that day's midnight, so the comparison only matched the exact midnight instant and silently excluded the rest of the day. Callers expect Le with a bare date to mean "on or before this date", not "before this date's midnight". Bump the parsed boundary to the last tick of the day when the raw filter value has no time component. A full timestamp value (with a time component) is left untouched. --- .../Extensions/QueryableExtensionTests.cs | 62 +++++++++++++++++++ .../Filtering/FilterExpressionComposer.cs | 25 ++++++++ 2 files changed, 87 insertions(+) diff --git a/JsonApiToolkit.Tests/Extensions/QueryableExtensionTests.cs b/JsonApiToolkit.Tests/Extensions/QueryableExtensionTests.cs index 6066e63..f704508 100644 --- a/JsonApiToolkit.Tests/Extensions/QueryableExtensionTests.cs +++ b/JsonApiToolkit.Tests/Extensions/QueryableExtensionTests.cs @@ -107,6 +107,68 @@ public void ApplyFilters_WithGreaterThanFilter_FiltersCorrectly() Assert.Equal(5, result[1].Id); } + [Fact] + public void ApplyFilters_WithLessThanOrEqualDateOnlyFilter_IncludesWholeDay() + { + // A date-only Le value (no time component) must include every moment + // of that day, not just its exact midnight instant. + var testData = new List + { + new TestEntity { Id = 1, CreatedAt = new DateTime(2026, 9, 14, 0, 0, 0) }, + new TestEntity { Id = 2, CreatedAt = new DateTime(2026, 9, 14, 15, 30, 0) }, + new TestEntity { Id = 3, CreatedAt = new DateTime(2026, 9, 14, 23, 59, 59) }, + new TestEntity { Id = 4, CreatedAt = new DateTime(2026, 9, 15, 0, 0, 0) }, + }.AsQueryable(); + + var filterGroup = new FilterGroup + { + Filters = new List + { + new FilterParameter + { + Field = "CreatedAt", + Operator = FilterOperator.Le, + Value = "2026-09-14", + }, + }, + }; + + var result = testData.ApplyFilters(filterGroup).ToList(); + + Assert.Equal(3, result.Count); + Assert.DoesNotContain(result, e => e.Id == 4); + } + + [Fact] + public void ApplyFilters_WithLessThanOrEqualFullTimestampFilter_DoesNotExtendToEndOfDay() + { + // A full timestamp (time component present) must be used exactly as + // given — only the bare date-only case gets the end-of-day bump. + var testData = new List + { + new TestEntity { Id = 1, CreatedAt = new DateTime(2026, 9, 14, 9, 0, 0) }, + new TestEntity { Id = 2, CreatedAt = new DateTime(2026, 9, 14, 15, 30, 0) }, + }.AsQueryable(); + + var filterGroup = new FilterGroup + { + Filters = new List + { + new FilterParameter + { + Field = "CreatedAt", + Operator = FilterOperator.Le, + Value = "2026-09-14T12:00:00", + }, + }, + }; + + var result = testData.ApplyFilters(filterGroup).ToList(); + + Assert.Single(result); + Assert.Equal(1, result[0].Id); + } + [Fact] public void ApplyFilters_WithLikeFilter_FiltersCorrectly() { diff --git a/JsonApiToolkit/Extensions/Querying/Filtering/FilterExpressionComposer.cs b/JsonApiToolkit/Extensions/Querying/Filtering/FilterExpressionComposer.cs index 265241f..53900a7 100644 --- a/JsonApiToolkit/Extensions/Querying/Filtering/FilterExpressionComposer.cs +++ b/JsonApiToolkit/Extensions/Querying/Filtering/FilterExpressionComposer.cs @@ -345,6 +345,21 @@ int depth return null; } + // A date-only value (no time component, e.g. "2026-09-14") used with + // Le against a DateTime property means "up to and including that + // whole day" to callers — but it parses to that day's midnight, so + // an unadjusted <= would only match the exact midnight instant and + // silently exclude the rest of the day. Bump it to the last tick of + // the day so Le behaves as "on or before this date". + if ( + filter.Operator == FilterOperator.Le + && filterValue is DateTime dateOnlyBoundary + && IsDateOnlyValue(filter.Value) + ) + { + filterValue = dateOnlyBoundary.Date.AddDays(1).AddTicks(-1); + } + ConstantExpression constant = Expression.Constant(filterValue, targetType); return filter.Operator switch @@ -604,4 +619,14 @@ private static void ThrowIfTooDeep(int depth, FilterParameter filter) } ); } + + /// + /// True if the raw filter value string carries no time-of-day component + /// (e.g. "2026-09-14"), as opposed to a full timestamp (e.g. + /// "2026-09-14T10:00:00"). ISO 8601 date-times always separate the time + /// with 'T' and represent time-of-day with ':', so the absence of both + /// is a reliable signal the caller only specified a calendar date. + /// + private static bool IsDateOnlyValue(string value) => + !value.Contains('T') && !value.Contains(':'); } From 763799cea7e98557675fa240c5e3b29e0d1f6a32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Na=CC=8Akkve=20Kierulf?= Date: Tue, 15 Sep 2026 08:54:18 +0200 Subject: [PATCH 2/2] build: regenerate TypeGen packages.lock.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Out of sync since JsonApiToolkit's own dependencies were bumped in #218/#221 — the TypeGen project references JsonApiToolkit, so its lock file needed to move too. Pre-existing on main (also failing on #221's own build-and-test check), unrelated to this branch's actual fix; regenerating it here so CI can pass. --- JsonApiToolkit.TypeGen/packages.lock.json | 158 +++++++++++----------- 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/JsonApiToolkit.TypeGen/packages.lock.json b/JsonApiToolkit.TypeGen/packages.lock.json index 46770c8..f155670 100644 --- a/JsonApiToolkit.TypeGen/packages.lock.json +++ b/JsonApiToolkit.TypeGen/packages.lock.json @@ -40,27 +40,27 @@ }, "Intility.Extensions.Logging": { "type": "Transitive", - "resolved": "3.1.6", - "contentHash": "de+ySanItzm3jrpKOqtwWa86hoRQmwuAjyIQX9Tj4JA8tbeV+0Mjs2V4auJ9boCsLcqSv75sK1Ac6fsY9zkcDw==", + "resolved": "3.1.7", + "contentHash": "slDca7FHqWrV53U+B7rkKZJXlcORFxn7Ux/Ku37XuJdZxfAc3SyD/yP3Gj/G1Ji8qvcnqo/+wQ2ZTG8TFo4Jew==", "dependencies": { - "Microsoft.Extensions.Hosting.Abstractions": "10.0.10", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.11", "Serilog": "4.4.0" } }, "Intility.Logging.AspNetCore": { "type": "Transitive", - "resolved": "3.1.6", - "contentHash": "6dYcQnj/5ZLnomhyHUFWppVr8dwjgp8KTqhYaHVtXC3pC8P2OtqjQIFkhlHJCrgLLUBVhKwiNLhVzYGUR1s7/g==", + "resolved": "3.1.7", + "contentHash": "uVNl/D+HAVh6A9AIaFT5QxQwrFG5BypwUfMQ3GFZ5pHoILAsCAqY3Z/YDkksN4mfUkGc20pVqLlyc8rOeO6j4w==", "dependencies": { - "Intility.Extensions.Logging": "3.1.6", - "Microsoft.Extensions.Hosting.Abstractions": "10.0.10", - "Microsoft.Extensions.Logging.Abstractions": "10.0.10", + "Intility.Extensions.Logging": "3.1.7", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.11", + "Microsoft.Extensions.Logging.Abstractions": "10.0.11", "Serilog.AspNetCore": "10.0.0", "Serilog.Enrichers.AssemblyName": "2.0.0", "Serilog.Enrichers.AzureClaims": "1.2.9", "Serilog.Enrichers.Environment": "3.0.1", "Serilog.Enrichers.Memory": "1.0.4", - "System.Security.Cryptography.Xml": "10.0.10" + "System.Security.Cryptography.Xml": "10.0.11" } }, "Microsoft.AspNetCore.Authentication.JwtBearer": { @@ -120,54 +120,54 @@ }, "Microsoft.EntityFrameworkCore": { "type": "Transitive", - "resolved": "10.0.11", - "contentHash": "VOSGU8en6HZJs8t7UMFN+9vGcRgVOOn6fA44Ngcg2NyvJ3P1KE94iAb0XzaVaGhXGtt+qaM/VtEn0/hzluQJeg==", + "resolved": "10.0.12", + "contentHash": "e7OrVN8U5yr4kuwdTHWBHGVQIVsGfMkAr0Ej1/BnrS989Q0XBVANpIzNZ2bc1GvMZ0/XwMt5InTnmKskxGy99Q==", "dependencies": { - "Microsoft.EntityFrameworkCore.Abstractions": "10.0.11", - "Microsoft.EntityFrameworkCore.Analyzers": "10.0.11", - "Microsoft.Extensions.Caching.Memory": "10.0.11", - "Microsoft.Extensions.Logging": "10.0.11" + "Microsoft.EntityFrameworkCore.Abstractions": "10.0.12", + "Microsoft.EntityFrameworkCore.Analyzers": "10.0.12", + "Microsoft.Extensions.Caching.Memory": "10.0.12", + "Microsoft.Extensions.Logging": "10.0.12" } }, "Microsoft.EntityFrameworkCore.Abstractions": { "type": "Transitive", - "resolved": "10.0.11", - "contentHash": "6auJR+9+9VunznKfH7WGrHMrnrmA0F7JZ22EXzwXvVhjfnbu9Xq7NSIWaOf3KJsOanM2qf5ajJ2JR5TlcPZTLA==" + "resolved": "10.0.12", + "contentHash": "kDrux7T6C3V/YYYe2LXr7x6AEsVyq5Y2YoTE9er1SwbDtap3z1g8RgxNh5eKQVyB4T+DKvBBJ4Ezd/VZzJQJZg==" }, "Microsoft.EntityFrameworkCore.Analyzers": { "type": "Transitive", - "resolved": "10.0.11", - "contentHash": "Bv7X4wSSnzCQED9WYXKJ8fwgyvKwf0xZM1GO8xkf6CF9zl+UBnvjxmcPnokJRy0JKjc1SlHSzzhx1HcL4jitTQ==" + "resolved": "10.0.12", + "contentHash": "Kd4o2oO1A6dfKxjz5LS16QyLtpCFTUiFWwmBABETAXRsSImBdRdWeKjSgbbRhAMiV3a3/nWr95ZtzClT4uaADQ==" }, "Microsoft.EntityFrameworkCore.Relational": { "type": "Transitive", - "resolved": "10.0.11", - "contentHash": "grznnTJgEYxaWpdKAsTzg6j+89jHgCXWYp+QGtlX5O92+w/VuhWM6JLPYb+uw8M9VhGUvOTsO76dYOy9vNPd5Q==", + "resolved": "10.0.12", + "contentHash": "OiHmr8XzX96dbgMsYGe8qoqg4KxibdZG2r0QUVJBGktFInOp8IrABe8jvcbo5hrqeWfbwpK7fCEBiEPbY/ik4A==", "dependencies": { - "Microsoft.EntityFrameworkCore": "10.0.11", - "Microsoft.Extensions.Caching.Memory": "10.0.11", - "Microsoft.Extensions.Configuration.Abstractions": "10.0.11", - "Microsoft.Extensions.Logging": "10.0.11" + "Microsoft.EntityFrameworkCore": "10.0.12", + "Microsoft.Extensions.Caching.Memory": "10.0.12", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.12", + "Microsoft.Extensions.Logging": "10.0.12" } }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", - "resolved": "10.0.11", - "contentHash": "vUl798SmruTqqlt/xH2gDk3tJlhk6k3HdOXAHirlRfbNKDym4g/kRpUL9S4sl6F6FsOTOMW+ZsDapqlZMOOiEw==", + "resolved": "10.0.12", + "contentHash": "sI3A6MUAyZwccLnwq0cXuRmC3WBtXieimBWafXSfhRJ4jnM2uGVXrqImDDVyW27u4vVaTOGlJxNJd8d1FGvCNQ==", "dependencies": { - "Microsoft.Extensions.Primitives": "10.0.11" + "Microsoft.Extensions.Primitives": "10.0.12" } }, "Microsoft.Extensions.Caching.Memory": { "type": "Transitive", - "resolved": "10.0.11", - "contentHash": "el1g0mBEbDBGY2bT9mcSfrTWO8QlPdq2nOCnvQugioOFwHV+bVBMeiakoI0dNOdj8d6Hi9K6HY2xzRUWJiDR3w==", + "resolved": "10.0.12", + "contentHash": "fhC3DHcBcFF4bXvHIxFtXJYNut7q7ZItqNFcgWfrIgmpVImlcEKNHhE7ztpNSPJYMHYYStS5QGND2I5mC26yeA==", "dependencies": { - "Microsoft.Extensions.Caching.Abstractions": "10.0.11", - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11", - "Microsoft.Extensions.Logging.Abstractions": "10.0.11", - "Microsoft.Extensions.Options": "10.0.11", - "Microsoft.Extensions.Primitives": "10.0.11" + "Microsoft.Extensions.Caching.Abstractions": "10.0.12", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.12", + "Microsoft.Extensions.Logging.Abstractions": "10.0.12", + "Microsoft.Extensions.Options": "10.0.12", + "Microsoft.Extensions.Primitives": "10.0.12" } }, "Microsoft.Extensions.Configuration": { @@ -181,10 +181,10 @@ }, "Microsoft.Extensions.Configuration.Abstractions": { "type": "Transitive", - "resolved": "10.0.11", - "contentHash": "fVi053xdpda9Em7vSkmgVxO/PtgC2m78ekReKWsgcyskqY0U82Bz/MONwxpGzI0hElYKJfw+fupqMVeKW3fSaA==", + "resolved": "10.0.12", + "contentHash": "8xaGcvS/qZ1otoxPQCEJkNva389CVL/plNcvIETZhQTETYdRkYDPEYhUMoAGONo4FU45ufdfE0j29AfWVVj0wA==", "dependencies": { - "Microsoft.Extensions.Primitives": "10.0.11" + "Microsoft.Extensions.Primitives": "10.0.12" } }, "Microsoft.Extensions.Configuration.Binder": { @@ -198,16 +198,16 @@ }, "Microsoft.Extensions.DependencyInjection": { "type": "Transitive", - "resolved": "10.0.11", - "contentHash": "PSmotV19c7E3lKed++uYo1kSiXFI+uTl37CBSrhq+CfLC3FCHjG7R91+xPnNehQfHS1b0Tzo/CCLPWH3qaEheg==", + "resolved": "10.0.12", + "contentHash": "lXyK2O5GoYvfxW8eCFcD16JFbcoSTM1sJkAM0UHS1jZyl9NYMW64Tqm6OQFT0IDBjZi+xHt95/Zg+nxZhGFhZg==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11" + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.12" } }, "Microsoft.Extensions.DependencyInjection.Abstractions": { "type": "Transitive", - "resolved": "10.0.11", - "contentHash": "/a1aJz4m7ylhEDf25ugQChLQoN5XwoGjWw/BoR/ZWWKsO1v4DdJElS1uyngahz4B/eOzjFk1KNTkarRLE5wsIg==" + "resolved": "10.0.12", + "contentHash": "9/qymSh7hVDMGTGwrLz8MRp5zRyXy9adGDOs4HwRdnLil3oZGYuWeZjbmHgCQ9BL1qBroVfgUK3U/nb61617Cw==" }, "Microsoft.Extensions.DependencyModel": { "type": "Transitive", @@ -216,58 +216,58 @@ }, "Microsoft.Extensions.Diagnostics.Abstractions": { "type": "Transitive", - "resolved": "10.0.10", - "contentHash": "9uWiKpeOVac355STyChWR/pliFX/5CeLqChW9kKsaxyDH4EUTZxMkT4Jwp/J/peLm0GBFmSX5c0WCse3yCnq1Q==", + "resolved": "10.0.11", + "contentHash": "se7Kx8QpJEt+nf26L4qIVAofGTDr1wbexxsh/Fm3Xc04xUkqUXK06KUS7FLwSQYSjqb7q9n+T7MEcXYBhI1Y5g==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.10", - "Microsoft.Extensions.Options": "10.0.10" + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11", + "Microsoft.Extensions.Options": "10.0.11" } }, "Microsoft.Extensions.FileProviders.Abstractions": { "type": "Transitive", - "resolved": "10.0.10", - "contentHash": "c5zqFCY9DiIpMovLd7/d/CTiEtrMOuQ639dhv3PABtKQIKNQikSHwQt8+N679uii9q+B55lgK28Uv64FOwEu8w==", + "resolved": "10.0.11", + "contentHash": "JOjac6SQQgZmdmB8WGEw61/7siqMZoWJMkmq2p1goJGxqI59lO6oB4bOl0jNsbaPBdYy5Mlkb+6U7T4+CjnD8Q==", "dependencies": { - "Microsoft.Extensions.Primitives": "10.0.10" + "Microsoft.Extensions.Primitives": "10.0.11" } }, "Microsoft.Extensions.Hosting.Abstractions": { "type": "Transitive", - "resolved": "10.0.10", - "contentHash": "5LugpYGHk+mkn0a8IZgcyfBca8PCTAU9RQFoMrTdtOOidq88M2SI5f3px6ugnzgxC+eTkvYYJi8pzlUnG5xdAQ==", + "resolved": "10.0.11", + "contentHash": "pwtpF7iF/NNaOBcX+pvMZ7y2+JAVbH5KkNrH9uMZtuVxVJsFTDiWiCR7Tk3HVptsAijaetipUZVRVK2LLq+nvA==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "10.0.10", - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.10", - "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.10", - "Microsoft.Extensions.FileProviders.Abstractions": "10.0.10", - "Microsoft.Extensions.Logging.Abstractions": "10.0.10" + "Microsoft.Extensions.Configuration.Abstractions": "10.0.11", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11", + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.11", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.11", + "Microsoft.Extensions.Logging.Abstractions": "10.0.11" } }, "Microsoft.Extensions.Logging": { "type": "Transitive", - "resolved": "10.0.11", - "contentHash": "nUOJwgFkSiLHiVGFpU22pIJtuWYewuSYQ3JVuP/gdK8ASMT807Px+TYQiRWs6uSsOmoyFTaVCwKXTasczV6BpA==", + "resolved": "10.0.12", + "contentHash": "6I46fTPfgYkrjRYfRXbho9WOvOelTnNjWuZws/hzGHDASH1LEJeA4VKK9k3wJvido8o7jJSB5WkMTonX7HM1bA==", "dependencies": { - "Microsoft.Extensions.DependencyInjection": "10.0.11", - "Microsoft.Extensions.Logging.Abstractions": "10.0.11", - "Microsoft.Extensions.Options": "10.0.11" + "Microsoft.Extensions.DependencyInjection": "10.0.12", + "Microsoft.Extensions.Logging.Abstractions": "10.0.12", + "Microsoft.Extensions.Options": "10.0.12" } }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", - "resolved": "10.0.11", - "contentHash": "Ljd0Uxoq5XpScD2Bg0nM/r3mwx7Ao5Uq24eo2ARxbGvqJ7Zht6rt2cJtwVRH4Cv+1ZVMdXz6TB43KbpmsxRrvQ==", + "resolved": "10.0.12", + "contentHash": "+24lC4plfbEDNfLAdTV/SWKS7dW+16X4HdydO3R++134kSNTzcbYA4KpR1Hdh6uWisB8Za3AzwyOn+K+NxWIug==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11" + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.12" } }, "Microsoft.Extensions.Options": { "type": "Transitive", - "resolved": "10.0.11", - "contentHash": "eY1GAKcTfD2maP27J84X9IovT3yjHJ2dVDzPmDg6/XqYvt3jMzJhtfQCLjG9pVsZGAd+8DQ2QrjaDcs2+VQLGw==", + "resolved": "10.0.12", + "contentHash": "TDYD33TSRpXKZWlmTXNlj5kCihxatmv2Ec1u6C+bMYLphCS7PoSLE9Pjd/nunDoE7yETk+LLKjVJX78HYtWjpA==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.11", - "Microsoft.Extensions.Primitives": "10.0.11" + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.12", + "Microsoft.Extensions.Primitives": "10.0.12" } }, "Microsoft.Extensions.Options.ConfigurationExtensions": { @@ -284,8 +284,8 @@ }, "Microsoft.Extensions.Primitives": { "type": "Transitive", - "resolved": "10.0.11", - "contentHash": "SXcz+kF+4Oo9b1+55zntpJFYfwb1jw66ioxptyNOOTDc8g2FHnBFWjZpsWfCvZIhzr0x+4e2trVTs4OKwQfBtw==" + "resolved": "10.0.12", + "contentHash": "dYfCLR52UA+3DL7C4I/pvSaRPkNqxrUAQmbFL2u0zvYKKzqgrFCJl08Df+F1aYc8leu9JvpC9bsURUdpExcBXQ==" }, "Microsoft.Identity.Abstractions": { "type": "Transitive", @@ -603,8 +603,8 @@ }, "System.Security.Cryptography.Pkcs": { "type": "Transitive", - "resolved": "10.0.10", - "contentHash": "KG8t5RHczdgB3IWvRndpI0nE1DSo7ikDYSDbITxfgRFyIvnYiKzuPjaZOsPnwFQ1aOGUl9sEulJul9wlHLEUoA==" + "resolved": "10.0.11", + "contentHash": "8IV+rI3xN/Mkq9MsSX7VZTv9T9Wt+tyhHLwBX9VNZBk8m8kknEs1JeTSjI2x9M2L/fSja+c2WSE5n5Yy0GXdoQ==" }, "System.Security.Cryptography.ProtectedData": { "type": "Transitive", @@ -613,18 +613,18 @@ }, "System.Security.Cryptography.Xml": { "type": "Transitive", - "resolved": "10.0.10", - "contentHash": "Mz6Y+s+uMQKj1H2BUF0OhlmaOQkLgSG34/IrUaBDirYBQ6bgwcFvO/XtXWcoDlBLFoFB0uKqDNhybHOd+fQK1A==", + "resolved": "10.0.11", + "contentHash": "TokfVsaU2fmcwvsU6ihLCkseVfwhLX6Tmbl3qh3nOBIqHSX4yqFllpslA+PuHERH/ENu3kwqo4deZiyT0Wvh3Q==", "dependencies": { - "System.Security.Cryptography.Pkcs": "10.0.10" + "System.Security.Cryptography.Pkcs": "10.0.11" } }, "Intility.JsonApiToolkit": { "type": "Project", "dependencies": { - "Intility.Logging.AspNetCore": "[3.1.6, )", - "Microsoft.EntityFrameworkCore": "[10.0.11, )", - "Microsoft.EntityFrameworkCore.Relational": "[10.0.11, )" + "Intility.Logging.AspNetCore": "[3.1.7, )", + "Microsoft.EntityFrameworkCore": "[10.0.12, )", + "Microsoft.EntityFrameworkCore.Relational": "[10.0.12, )" } } }