如何访问 Npgsql 4.0 通用参数中的 TypedValue

How to Access TypedValue in Npgsql 4.0 Generic Parameters

跟进以下话题:

对于允许强类型值的新通用参数,文档指出声明看起来像这样:

cmd.Parameters.Add(new NpgsqlParameter<int>("ID", 15));

这将在参数上设置 TypedValue 属性。

但是,当我对同一命令进行多次插入时,我似乎无法直接访问 TypedValue。有没有允许这样做的结构?下面是我正在使用的示例,我将每个参数转换为其类型化的对应项:

using (NpgsqlTransaction trans = conn.BeginTransaction(IsolationLevel.RepeatableRead))
{
    using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn, trans))
    {
        cmd.Parameters.Add(new NpgsqlParameter<Int32>("ID",
            NpgsqlTypes.NpgsqlDbType.Integer));
        cmd.Parameters.Add(new NpgsqlParameter<String>("TRAY_CODE", 
            NpgsqlTypes.NpgsqlDbType.Varchar));

        foreach (ReturnScrapDecision newRecord in NewRecords)
        {
            ((NpgsqlParameter<Int32>)cmd.Parameters[0]).TypedValue = newRecord.Id;
            ((NpgsqlParameter<String>)cmd.Parameters[1]).TypedValue = newRecord.TrayCode;

            cmd.ExecuteNonQuery();
        }
    }

    trans.Commit();
}

顺便说一句,上面的代码可以编译,但我还不知道它是否会 运行。我还在测试。

我可以设置Value很好:

cmd.Parameters[0].Value = newRecord.Id;

但我不能不转换就做这个:

cmd.Parameters[0].TypedValue = newRecord.Id;

NpgsqlCommand.ParametersIList<NpgsqlParameter> - 非通用类型。因此,当您执行 cmd.Parameters[0] 时,您得到的是经典 NpgsqlParameter 而不是 NpgsqlParameter<T>

你可以使用向下转型:

((NpgsqlParameter<int>)cmd.Parameters[0]).TypedValue = newRecord.Id;

或者更好的是,在分配参数时只使用初始化程序:

    cmd.Parameters.Add(new NpgsqlParameter<Int32>("ID", NpgsqlTypes.NpgsqlDbType.Integer) { TypedValue = newRecord.Id });

(添加答案,因为我无法发表评论...)

TypedParameters 属性 的问题是您最终会得到一个混合类型的集合,并且仍然需要转换它们。

这样的解决方案怎么样?

using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn, trans))
{
    var idParam = new NpgsqlParameter<Int32>("ID", NpgsqlTypes.NpgsqlDbType.Integer);
    cmd.Parameters.Add(idParam);
    var trayCodeParam = new NpgsqlParameter<String>("TRAY_CODE", NpgsqlTypes.NpgsqlDbType.Varchar);
    cmd.Parameters.Add(trayCodeParam);

    foreach (ReturnScrapDecision newRecord in NewRecords)
    {
        idParam.TypedValue = newRecord.Id;
        trayCodeParam.TypedValue = newRecord.TrayCode;
        cmd.ExecuteNonQuery();
    }
}