Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Writing values of 'NpgsqlTypes.NpgsqlRange`1[[System.TimeSpan, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]][]' is not supported for parameters having NpgsqlDbType '-2147483608'. #3137

Open
NazarPolevyi opened this issue Mar 24, 2024 · 3 comments

Comments

@NazarPolevyi
Copy link

NazarPolevyi commented Mar 24, 2024

Steps to reproduce

Hi, after Npgsql.EntityFrameworkCore.PostgreSQL update from to 7.0.4 to 8.0.2. We have started to receive an exception when saving into db.
InvalidCastException: Writing values of 'NpgsqlTypes.NpgsqlRange`1[[System.TimeSpan, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]][]' is not supported for parameters having NpgsqlDbType '-2147483608'.


public class RestrictionSettings
{
    [Column("id")]
    public Guid Id { get; set; }

    [Column("allowed_time_ranges", TypeName = "timerange[]")]
    public NpgsqlRange<TimeSpan>[]? AllowedTimeRanges { get; set; }
}

private readonly NpgsqlDataSource _dataSource;
private readonly ILoggerFactory _loggerFactory;

public class CustomDbContext : DbContext
{
    private readonly NpgsqlDataSource _dataSource;
    private readonly ILoggerFactory _loggerFactory;

    public CustomDbContext (NpgsqlDataSource dataSource, ILoggerFactory loggerFactory)
    {
        _dataSource = dataSource;
        _loggerFactory = loggerFactory;
    }

    public DbSet<RestrictionSettings> RestrictionSettings{ get; set; }

  protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
  {
      if (!optionsBuilder.IsConfigured)
      {
          optionsBuilder
              .UseLoggerFactory(_loggerFactory)
              .UseNpgsql(
                  _dataSource,
                  o => o
                      .SetPostgresVersion(new Version(10, 21))
                      .MapRange<TimeSpan>("timerange", subtypeName: "time without time zone"));

          optionsBuilder
              .EnableDetailedErrors()
              .EnableSensitiveDataLogging();
      }
  }

 protected override void OnModelCreating(ModelBuilder modelBuilder)
 {
     modelBuilder.HasPostgresRange(name: "timerange", subtype: "time without time zone");
  }
}

Registration example

  services.AddSingleton<Func<CustomDbContext>>(p => () =>
      {
          var connectionString = "connection string";

          var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString);
          dataSourceBuilder.EnableDynamicJson().EnableUnmappedTypes();
          var dataSource = dataSourceBuilder.Build();

          return new CustomDbContext (
              dataSource,
              p.GetRequiredService<ILoggerFactory>());
      });

The timerange it's a custom timerange type:

` CREATE FUNCTION time_subtype_diff(x time, y time) RETURNS float8 AS
'SELECT EXTRACT(EPOCH FROM (x - y))' LANGUAGE sql STRICT IMMUTABLE;

CREATE TYPE timerange AS RANGE (
    subtype = time without time zone,
    subtype_diff = time_subtype_diff
);`

How can we solve this error? Before update it was working,

Exception message:
`Microsoft.EntityFrameworkCore.DbUpdateException
  HResult=0x80131500
  Message=An error occurred while saving the entity changes. See the inner exception for details.
  Source=Microsoft.EntityFrameworkCore.Relational
  StackTrace:
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.<ExecuteAsync>d__50.MoveNext()
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.<ExecuteAsync>d__9.MoveNext()
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.<ExecuteAsync>d__9.MoveNext()
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.<ExecuteAsync>d__9.MoveNext()
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<SaveChangesAsync>d__111.MoveNext()
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<SaveChangesAsync>d__115.MoveNext()
   at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlExecutionStrategy.<ExecuteAsync>d__7`2.MoveNext()
   at Microsoft.EntityFrameworkCore.DbContext.<SaveChangesAsync>d__63.MoveNext()
   at Microsoft.EntityFrameworkCore.DbContext.<SaveChangesAsync>d__63.MoveNext()
   at 

  This exception was originally thrown at this call stack:
    [External Code]
Inner Exception 1:
InvalidCastException: Writing values of 'NpgsqlTypes.NpgsqlRange`1[[System.TimeSpan, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]][]' is not supported for parameters having NpgsqlDbType '-2147483608'.
`
@NinoFloris
Copy link
Member

NinoFloris commented Mar 25, 2024

@roji this might be related to https://github.com/npgsql/npgsql/pull/5123/files#r1325747341

If so setting the actual datatypename of the range on the param should solve it.

EDIT: traced the regstration to

var unquotedRangeStoreType = rangeDefinition.SchemaName is null
which suggests that's already happening. Not sure how we end up with a is not supported for parameters having NpgsqlDbType kind of error. That only happens if it was set somehow.

@NinoFloris
Copy link
Member

NinoFloris commented Mar 25, 2024

@NazarPolevyi

I notice your entity has the following attribute

  [Column("allowed_time_ranges", TypeName = "timerange[]")]
    public NpgsqlRange<TimeSpan>? AllowedTimeRanges { get; set; }

Specifically timerange[] while the clr type is not an array/list. Can you remove [] and try again?

@NinoFloris NinoFloris transferred this issue from npgsql/npgsql Mar 25, 2024
@NazarPolevyi
Copy link
Author

NazarPolevyi commented Mar 25, 2024

@NinoFloris
Thanks for answer.
@roji What do you think?

I'm sorry. The issue is actually related to array of ranges NpgSqlRange<TimeSpan>[]. So the entity class should look like this.

public class RestrictionSettings
{
    [Column("id")]
    public Guid Id { get; set; }

    [Column("allowed_time_ranges", TypeName = "timerange[]")]
    public NpgsqlRange<TimeSpan>[]? AllowedTimeRanges { get; set; }
}

Usual NpgSqlRange<TimeSpan> works fine.


public class RestrictionSettings
{
    [Column("id")]
    public Guid Id { get; set; }

    [Column("allowed_time_ranges", TypeName = "timerange")]
    public NpgsqlRange<TimeSpan> AllowedTimeRanges { get; set; }
}

Is it possible to use array(NpgsqlRange[]) now in 8.02 version?
Btw, NpgsqlRange<DateTime>[] works well without specifying custom range type. But for the NpgsqlRange<TimeSpan>[] it's not

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

No branches or pull requests

2 participants