Search code examples
c#postgresqlnpgsql

How to Access TypedValue in Npgsql 4.0 Generic Parameters


Follow-up on the following thread:

Npgsql 4.0 Parameters and Null Values

For the new Generic Parameters that allow strongly typed values, the docs indicate that the declaration would look something like this:

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

Which would set the TypedValue property on the parameter.

However, when I have multiple inserts for the same command, I can't seem to access TypedValue directly. Is there a construct that would allow this? Below is the example I'm working with, where I'm casting each parameter as its typed counterpart:

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

By the way, the code above compiles, but I have no idea yet if it will run or not. I'm still testing that.

I can set Value fine:

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

But I cannot do this without casting:

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

Solution

  • NpgsqlCommand.Parameters is an IList<NpgsqlParameter> - of the non-generic kind. So when you do cmd.Parameters[0] you're getting back a classic NpgsqlParameter and not NpgsqlParameter<T>.

    You can use downcasting:

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

    Or better yet, just use an initializer when you allocate the parameter:

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