C# with Npgsql - 无法使用处理程序类型 Int32Handler 编写 CLR 类型 System.String

C# with Npgsql - Can't write CLR type System.String with handler type Int32Handler

我在尝试将整数添加到 Postgresql 数据库时遇到问题。 Varchars 工作正常,但是当我使用代码时:

var parameter = cmd.CreateParameter();
parameter.Value = Int32.Parse(x.Value.ToString());
Console.WriteLine(parameter.Value);
parameter.ParameterName = x.Key.ToString();
cmd.Parameters.Add(new NpgsqlParameter("confirmations",NpgsqlTypes.NpgsqlDbType.Integer));
for (int search=0; search != cmd.Parameters.Count; search++)

执行时出错,我正在使用:

 cmd.ExecuteNonQuery();

听起来像:

Database problem: System.InvalidCastException: Can't write CLR type System.String with handler type Int32Handler\

at lambda_method(Closure , NpgsqlTypeHandler , Object , NpgsqlLengthCache& , NpgsqlParameter )

at Npgsql.NpgsqlParameter.ValidateAndGetLength() in C:\projects\npgsql\src\Npgsql\NpgsqlParameter.cs:line 553

at Npgsql.NpgsqlCommand.ValidateParameters() in C:\projects\npgsql\src\Npgsql\NpgsqlCommand.cs:line 793

at Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior, Boolean async, CancellationToken cancellationToken) in C:\projects\npgsql\src\Npgsql\NpgsqlCommand.cs:line 1141

at Npgsql.NpgsqlCommand.ExecuteNonQuery(Boolean async, CancellationToken cancellationToken) in C:\projects\npgsql\src\Npgsql\NpgsqlCommand.cs:line 1042

at Npgsql.NpgsqlCommand.ExecuteNonQuery() in C:\projects\npgsql\src\Npgsql\NpgsqlCommand.cs:line 1025

at BitcoinType.DatabaseManager.MakeInsert(Dictionary`2 requestData) in /Users/kamilkostrzewski/Projects/BitcoinType/BitcoinType/Program.cs:line 261

没有帮助我。

很难理解上面的代码示例 - 您创建并填充了 parameter,但随后在评论中添加了一个完全不同的 NpgsqlParameter 实例。

但是,错误消息清楚地表明您正在尝试将字符串写为整数。当您将 NpgsqlParameter.Value 设置为字符串值,但将其 NpgsqlDbType 设置为 Integer 时,就会发生这种情况。要么完全省略设置 NpgsqlDbType(Npgsql 通常会从值中推断出正确的类型),要么确保它们正确对齐。

假设您有以下 table:

create table foo (
  bar integer
)

如果您准备插入 table 如下:

NpgsqlCommand cmd = new NpgsqlCommand("insert into foo values (:BAR)", conn);
cmd.Parameters.Add(new NpgsqlParameter("BAR", NpgsqlDbType.Integer));

很明显这会引发错误:

cmd.Parameters[0].Value = "Hello";
cmd.ExecuteNonQuery();

出于同样的原因,这会引发错误:

insert into foo values ('Hello')

这显然有效,因为它是一个整数:

cmd.Parameters[0].Value = 5;

但您可能不知道以下内容仍然有效,因为它们是兼容的数据类型:

cmd.Parameters[0].Value = 5M;
cmd.Parameters[0].Value = 5f;
cmd.Parameters[0].Value = (short)5;
cmd.Parameters[0].Value = (long)5;

然而,即使 PostgreSQL 有足够的容忍度来接受原始 SQL:

insert into foo values ('5')

Npgsql 4 将在您尝试执行此操作时抛出您提到的错误:

cmd.Parameters[0].Value = "5";
cmd.ExecuteNonQuery();

有趣的是,我很确定它与 Npgsql 一起工作 3.x,但我认为该错误是一种改进。

因为它需要一个数字数据类型,简单的解决方案是确保你分配的任何 .Value 也是一个数字数据类型,最好是一个整数:

cmd.Parameters[0].Value = Convert.ToInt32(yourObject);
cmd.ExecuteNonQuery();

关于错误捕获的标准警告和使用 int.TryParse

从您上面的代码来看,您实际上可能正在将可能已经作为整数存在的内容转换为字符串。如果您取消所有这些,您可能会发现它开箱即用。在任何情况下,.Value 属性 都需要是数字。

我遇到了这个问题,我是这样解决的。在我的数据库中,我有一个类型为 Integer 的列。如果要向此列添加数据,您应该使用 NpgsqlDbType.Integer 数据类型。但是当我使用 NpgsqlDbType.String 数据类型时,我得到了那个错误。

所以你应该改变你的 NpgsqlDBtType。希望对你有帮助。

我在使用以下代码时遇到了同样的问题

  var utctime = DateTimeOffset.UtcNow.ToString("yyyy-MM-dd HH:mm:ss");
  writer.Write(utctime, NpgsqlDbType.TimestampTz);

所以基本上您是将 utctime 转换为字符串,但在写入数据库时​​使用类型作为时间戳,这不是字符串。因此它会抛出错误,因为数据与数据类型不兼容。

修复方法是不要将 utctime 转换为字符串,只需按原样使用即可。所以工作解决方案是

  var utctime = DateTimeOffset.UtcNow;
  writer.Write(utctime, NpgsqlDbType.TimestampTz);