5

In Npgsql V2, I could use the following code to update a record, and return the updated record values using a single Npgsql command.

The command.CommandText property contains both an UPDATE statement and also a SELECT statement. The idea being that when command.ExecuteReader is called both commands will run, but the results from the SELECT command will be returned (since it was the last command).

After upgrading to Npgsql version 3.0.3.0 the value in the datareader (from the SELECT statement) is still the original value, and not the updated one (the Return dr("action") line in the code). I have tried every different IsolationLevel and they all give the same results (as though the SELECT statement is not seeing the updated value from the INSERT statement). The value is properly updated in the database (if I re-query the record it has the updated value).

I can split this and use two separate NpgsqlCommand (one for the INSERT, and a second for the SELECT), but I don't want to create a second round-trip to the server.

This is a simplified function, the purpose of the real function is to update a record on the DB server, and then update the object in the application with any other fields that the server updated (such as the "last_updated" timestamp field which is updated on the server each time a record is updated).

Is there a way to make this work with Npgsql V3.0.3.0?

Public Function UpdateRecordExample(id As Guid, newAction As String) As String
        Using conn As New NpgsqlConnection("Connection String Here")
            Using trans = conn.BeginTransaction(IsolationLevel.ReadUncommitted)
                Dim command = conn.CreateCommand
                command.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord
                command.CommandText = "Update pm.action_item SET action=@action WHERE id=@id; SELECT * FROM pm.action_item WHERE id=@ID;"
                command.Parameters.Add(New NpgsqlParameter("id", id))
                command.Parameters.Add(New NpgsqlParameter("action", newAction))
                Using dr = command.ExecuteReader
                    If dr.Read Then
                        Return dr("action") 'This is still the original value and not "newAction"
                    Else
                        Throw New DBConcurrencyException
                    End If
                End Using
            End Using
        End Using
    End Function
6
  • thanks for posting this, it definitely shouldn't happen. I'm investigating things with the PostgreSQL devs and will post back here soon. Commented Oct 3, 2015 at 9:05
  • While this doesn't really answer your question, I really suggest avoiding multi-statements like that. Also, are you sure you're avoiding round-trips? PgJDBC at least splits up multi-statements and executes each one separately. nPgSQL might too. What you should ideally do - if nPgSQL has a similar interface to PgJDBC for this - is issue a batch of statements. If nPgSQL doesn't support batches, it might be worth adding support for them; doing so may not be that hard, and the performance boost is immense. Commented Oct 3, 2015 at 10:08
  • @ShayRojansky can you confirm if this concept is valid and really will avoid a second round trip? I did notice that the NpgsqlCommand object does separate the command text into multiple statements (it is almost like each statement is being run in parallel instead of being run sequentially). I assumed that adding multiple statements to NpgsqlCommand.CommandText was effectively like issuing a batch of sequential statements. Commented Oct 3, 2015 at 14:21
  • 1
    .NET's database API, ADO.NET, supports batching just like you're doing - inserting multiple SQL statement into a single command's CommandText (there's no separate batching API unfortunately). Npgsql 3.x implements this by splitting on semicolons and then sending all PostgreSQL protocol messages together (in a single packet if possible). So the performance optimization is definitely there - only one roundtrip. I'm not sure why things are misbehaving when the second query depends on the first though... Commented Oct 3, 2015 at 15:31
  • @Casey, I've confirmed it's a bug with the way Npgsql communicates with PostgreSQL. Can you please open an issue for this on github.com/npgsql/npgsql? Commented Oct 4, 2015 at 15:54

1 Answer 1

2

Note that this issue was resolved in Npgsql 3.1.

Sign up to request clarification or add additional context in comments.

1 Comment

Works great. Thanks to you and the rest of the Npgsql team for all your excellent work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.