Reputation: 23
I am trying to create a simple server (.Net Core 5.0), that communicates with PostgreSQL DB (v 13.1) via Npgsql + Npgsql.EntityFramework.
I have code that creates a new user, grants some rights and retrieves OID:
string connString =
String.Format(
"Server={0};Username={1};Database={2};Port={3};Password={4};SSLMode=Prefer",
PSqlHost, User, DBname, PSqlPort, Password);
NpgsqlConnection psqlConnection = null;
try
{
using (psqlConnection = new NpgsqlConnection(connString))
{
psqlConnection.Open();
StringBuilder cmdBuilder = new StringBuilder();
cmdBuilder.Append(string.Format("CREATE USER {0} WITH LOGIN PASSWORD '{1}';\r\n", signIn.Login, signIn.Pass));
cmdBuilder.Append(string.Format("GRANT SELECT ON ALL TABLES IN SCHEMA public TO {0};\r\n", signIn.Login));
cmdBuilder.Append(string.Format("GRANT SELECT, UPDATE ON ALL TABLES IN SCHEMA users TO {0};\r\n", signIn.Login));
cmdBuilder.Append(string.Format("SELECT oid FROM pg_catalog.pg_authid WHERE rolname='{0}';\r\n", signIn.Login));
using (var pgCmd = psqlConnection.CreateCommand())
{
pgCmd.CommandText = cmdBuilder.ToString();
if (!pgCmd.IsPrepared) pgCmd.Prepare();
using (var reader = pgCmd.ExecuteReader())
{
if (!reader.HasRows) return TcpMessageSpec.Fail;
if (!reader.IsOnRow) reader.Read();
var oid = (uint)reader.GetValue(0);
}
}
}
return TcpMessageSpec.OK;
}
catch (PostgresException ex)
{
Log.Exception(ex.MessageText);
if (ex.SqlState == PostgresErrorCodes.InvalidPassword) return TcpMessageSpec.AuthFailed;
else if (ex.SqlState == PostgresErrorCodes.DuplicateObject) return TcpMessageSpec.UserExists;
return TcpMessageSpec.ConnectionFailed;
}
catch (Exception ex)
{
Log.Exception(ex.InnerException);
return TcpMessageSpec.ConnectionFailed;
}
finally
{
}
This code perfectly works from a single thread, but I want it to work from multiple threads.
When I run this code from five or more threads, I catch PostgresException: "XX000: tuple concurrently updated"
. However, some threads succeed (no exception, OID is retrieved).
Attempts to solve (but the same result):
But still I do not understand where my mistake is.
Upvotes: 0
Views: 372
Reputation: 16722
tuple concurrently updated
is an error PostgreSQL sometimes returns when certain DDL operations are performed concurrently (see e.g. this discussion). This doesn't have anything to do with Npgsql - you're probably going to have to use synchronization to make sure these DDL operations don't happen in parallel.
Upvotes: 1