Npgsql 4.0参数和空值

时间:2018-07-24 15:01:27

标签: 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();
}

哪个工作正常。

新的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();
}

传递DBNull.Value时,将引发一般异常:

  

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

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

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

2 个答案:

答案 0 :(得分:3)

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

请注意,正如the documentation note所说,通用API的全部要点是避免使用Value类型的object属性。如果您使用通用NpgsqlParameter<int>却分配了Value,则您的int将被装箱,这违反了API的目的。您应该分配给TypedValue,类型为int,并且不要装箱。这也是为什么您无法分配DBNull.Value来指示空值(这是一种不同的.NET类型)的原因。

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

  • 如果您要编写很多值类型(例如intDateTime ...),这将删除所有装箱分配。这是否有意义取决于您的应用程序-仔细配置。
  • 通常,当在编译时知道通用API的类型时,一般应优先使用通用API。这样一来,编译器可以及早检查类型正确性,并使代码更清晰-即使性能不是问题,我们也使用List<string>而不是ArrayList来进行良好的编码
  • 通用API的主要(唯一?)缺点是特定于Npgsql,使您的代码不可移植到其他数据库驱动程序(尽管使用an issue exists使其成为ADO的一部分)。 NET)。

答案 1 :(得分:0)

我遇到了这个问题,现在我没有例外了

这是我为Postgres函数声明参数的方式:

string test;
using (NpgsqlCommand cmd = new NpgsqlCommand("insert into foo values (:TEST)", conn))
{
    cmd.Parameters.AddWithValue("TEST", NpgsqlTypes.NpgsqlDbType.Varchar, (object)test?? DBNull.Value);
    cmd.ExecuteNonQuery();
}