C# Npgsql 4.0参数和空值

C# Npgsql 4.0参数和空值,c#,postgresql,npgsql,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传递空值的方式如下:

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();
}
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();
}
这很好用

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

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();
}
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();
}
使用(npgsqlcmd=newnpgsqlcommand(“插入到foo值(:TEST)”,conn))
{
Add(新的npgsqldParameter(“TEST”,NpgsqlDbType.Varchar));
cmd.Parameters[0].Value=DBNull.Value;
cmd.ExecuteNonQuery();
}
传递DBNull.Value时,将引发常规异常:

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

所有东西仍然可以使用新的无装箱参数,但新语法似乎有意义,我们希望使用它。。。但是如何解决这种数据类型断开


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

我面临这个问题,现在我没有例外

下面是我如何声明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();
}

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

请注意,如前所述,通用API的全部要点是避免使用
Value
属性,该属性的类型为
object
。如果使用泛型
npgsql参数
,但分配
,则int将被装箱,从而破坏API的用途。您应该分配给
TypedValue
,它的类型为
int
,并且不会装箱。这也是为什么不能分配
DBNull.Value
来指示空值(它是不同的.NET类型)

关于是否应使用此新的通用API的一些注意事项:

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

这也适用于我,但当我使用未绑定版本的NpgsqlParameter时,我遇到了这个问题。使用
npgsqlparmeter
尝试一下,我怀疑您会得到与我相同的错误。@Hambone为什么需要使用它?啊!我明白你的意思,但在这种情况下,我认为只使用boxed参数是更少的工作和更防弹的。例如,关于日期、时间戳、数字、JSON、XML等,等等。简单地说,通用参数API确实是推荐的方式——它既不需要更多的工作,也不需要更多的防弹性——日期/时间戳或任何其他类型都不会使它们更适合传统的非通用API。但是,请注意,性能优势(保存分配)仅与值类型(例如int、DateTime)相关,而与已在堆上分配的字符串无关。使用通用参数API需要注意的唯一问题是,它特定于Npgsql-您的代码对其他数据库的可移植性较差(至少在它进入ADO.NET之前)。我完全错过了关于
TypedValue
的部分。感谢您的澄清和所有附加信息。这是完美的。我希望它的另一个优点是,它会在类型不匹配时发出编译时错误/警告,所以我会找出是否是这样。至于不可移植,对我来说更好更好,所以我宁愿使用它,而不是不使用。PostgreSQL数组也可以这么说——不是很好移植,但很神奇。说到神奇,NpgSql非常棒。感谢您对一个优秀产品的所有贡献。感谢所有的积极反馈…!是的,因为
TypedValue
是键入的,它将防止一些不匹配问题(严格类型总是比弱类型好…)