efcore.pg: DateTime.Now.AddDays(-1) throw Npgsql.PostgresException

This always works

DateTime changedAfter = DateTime.Now.AddDays(-1);

await _context.Entity
    .Where(e => e.Updated > changedAfter)
    .ToListAsync();

My understanding is that your translater now translate a specific DateTime, which always works.

This throws exception on a certain environment

Getting an exception on linux docker container (microsoft/dotnet:2.2.2-aspnetcore-runtime) in english/utc timezone with Npgsql.EntityFrameworkCore.PostgreSQL 2.2.0, with Microsoft.AspNetCore.App 2.2.2.

Strangly enough, it dont throw an exception on my development environment which is windows 10, norwegian/utc+2 timezoned. Against the same database with the same runtime version.

await _context.Entity
    .Where(e => e.Updated > DateTime.Now.AddDays(-1))
    .ToListAsync();

My understanding is that now you are translating AddDays(-1), which fails.

Npgsql.PostgresException
22007: invalid input syntax for type interval: "−1 days"

Npgsql.PostgresException (0x80004005): 22007: invalid input syntax for type interval: "−1 days"
   at Npgsql.NpgsqlConnector.<>c__DisplayClass161_0.<<ReadMessage>g__ReadMessageLong|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Npgsql.NpgsqlConnector.<>c__DisplayClass161_0.<<ReadMessage>g__ReadMessageLong|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Npgsql.NpgsqlDataReader.NextResult(Boolean async, Boolean isConsuming)
   at Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior, Boolean async, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteAsync(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 parameterValues, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.BufferlessMoveNext(DbContext _, Boolean buffer, CancellationToken cancellationToken)
   at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.MoveNext(CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.AsyncSelectEnumerable`2.AsyncSelectEnumerator.MoveNext(CancellationToken cancellationToken)
   at System.Linq.AsyncEnumerable.SelectEnumerableAsyncIterator`2.MoveNextCore(CancellationToken cancellationToken) in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\Select.cs:line 106
   at System.Linq.AsyncEnumerable.AsyncIterator`1.MoveNext(CancellationToken cancellationToken) in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\AsyncIterator.cs:line 98
   at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancellationToken)
   at System.Linq.AsyncEnumerable.Aggregate_[TSource,TAccumulate,TResult](IAsyncEnumerable`1 source, TAccumulate seed, Func`3 accumulator, Func`2 resultSelector, CancellationToken cancellationToken) in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\Aggregate.cs:line 120
   at Dyrket.NotifySubscriptionChangesJob.GetRecentlyChangedSubscriptionsAsync(Int32 forSupplierId) in /app/Dyrket/Jobs/Subscription/NotifySubscriptionChangesJob.cs:line 56
   at Dyrket.NotifySubscriptionChangesJob.RunAsync(IJobCancellationToken cancellationToken) in /app/Dyrket/Jobs/Subscription/NotifySubscriptionChangesJob.cs:line 34

Thanks for an otherwise very stable/reliable implementation of EF Core!

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 29 (17 by maintainers)

Most upvoted comments

a slightly related thing, the actual character in the source code file may also matter depending on the encoding of the file it is difficult to figure out the difference.

@Andrioden just to be clear, even if the fix we pushed doesn’t address your issue, it’s still important - there are various other culture-related bugs that it prevents.

@austindrenski are you able to continue investigating this?

What is it that I dont understand?

I think you’re on the same page as we are. This wasn’t something we were able to test/reproduce locally, so this patch was an educated guess based on previous, similar-sounding issues that were fixed by ensuring literal generation used the invariant culture.

How is the problem related to Norwegian? Where do my Norwegian environment impact this?

Frankly, we’re not sure. Culture issues have caused similar issues in the past, so it was an easy place to start looking.

Just to be really clear, we’re not blaming the Norwegian culture settings. If it is a culture issue, then it’s on us to wrap things in the invariant culture.

In a way it makes sense that this is an Norwegian culture problem, otherwise many others must have the same problem as me, but how. O.o

By the way, thanks for providing the additional info on your setup/codepages. We’ll have to take another look on our end.

new SqlFragmentExpression($“INTERVAL ‘{amountToAdd} {datePart}’”);

Interpolated strings are culture specific. EF Core codebase specifically avoids interpolated strings unless combining strings due to this. I believe right thing to do here is just use string.Format with invariant culture. Using interpolated string vs string.Format is purely coding preference and no functional impact. I would suggest checking other places in the codebase also where you using string interpolation with non-strings. For reference https://github.com/aspnet/EntityFrameworkCore/pull/5879

@austindrenski Keep in mind it works on my norwegian culture dev environment, but not on the linux docker container environment which is not an norwegian culture.