Npgsql 4.0 参数和空值

Ham*_*one 10 c# postgresql npgsql

使用 Npgsql 传递空值看起来像这样:

using (NpgsqlCommand cmd = new NpgsqlCommand("insert into foo values (:TEST)", conn))
{
    cmd.Parameters.Add(new NpgsqlParameter("TEST", NpgsqlDbType.Varchar));
    cmd.Parameters[0].Value = DBNull.Value;

    cmd.ExecuteNonQuery();
}
Run Code Online (Sandbox Code Playgroud)

哪个工作正常。

新的 Npgsql 4.0 文档建议使用强数据类型声明参数,如下所示:

using (NpgsqlCommand cmd = new NpgsqlCommand("insert into foo values (:TEST)", conn))
{
    cmd.Parameters.Add(new NpgsqlParameter<string>("TEST", NpgsqlDbType.Varchar));
    cmd.Parameters[0].Value = DBNull.Value;

    cmd.ExecuteNonQuery();
}
Run Code Online (Sandbox Code Playgroud)

当传递 DBNull.Value 时,会抛出一般异常:

无法将“System.DBNull”类型的对象转换为“System.String”类型。

一切仍然适用于新的无装箱参数,但新语法似乎有意义,我们想使用它......但如何解决这种数据类型断开连接?

上面的例子是一个字符串。我认为这也会影响数字和日期。

Sha*_*sky 7

新的通用参数 API 确实有问题 - 它应该接受常规 .NET null(而不是DBNull.Value),我已经打开这个问题来跟踪这个,它将在 4.0.3 中修复。

请注意,正如文档说明所说,通用 API 的重点是避免使用Value类型为的属性object。如果您使用泛型NpgsqlParameter<int>但分配Value,您的 int 将被装箱,从而违背 API 的目的。您应该分配给TypedValue,这是类型int并且不会装箱。这也是您不能分配DBNull.Value以指示空值(它是不同的 .NET 类型)的原因。

关于是否应该使用这个新的通用 API 的一些说明:

  • 如果您正在编写大量值类型(例如intDateTime...),这将删除所有装箱分配。这是否重要取决于您的应用程序 - 仔细配置文件。
  • 当类型在编译时已知时,泛型 API 通常应始终优先于非泛型 API。这允许编译器及早检查类型正确性并使您的代码更清晰 -即使性能不是问题,我们也使用List<string>而不是ArrayList作为良好编码的问题
  • 通用 API 的主要(唯一?)缺点是它是特定于 Npgsql 的,使您的代码不可移植到其他数据库驱动程序(尽管将这个(或类似的东西)作为 ADO.NET 的一部分存在问题)。