int parCount = 0;
int rowCount = 0;
using (NpgsqlConnection conn = new NpgsqlConnection("Server=10.140.96.45;Port=5432;Database=szgdb;User Id=dba;Password=sql;")) {
conn.Open();
using (NpgsqlTransaction trans = conn.BeginTransaction()) {
using (NpgsqlCommand cmd = new NpgsqlCommand("insert into public.\"Test\" values (:Par1)", conn, trans)) {
for (int i = 0; i < 3; i++) {
cmd.Parameters.AddWithValue("Par1", i);
int cnt = cmd.ExecuteNonQuery();
}
parCount = cmd.Parameters.Count;
}
using (NpgsqlCommand cmd = new NpgsqlCommand("select count(*) from public.\"Test\"", conn, trans)) {
rowCount = Convert.ToInt32(cmd.ExecuteScalar());
}
trans.Rollback();
}
}
Console.WriteLine("Parameters: {0}\t\tRows: {1}", parCount, rowCount);
Behavior of both apps was the same - "Parameters: 3 Rows: 3" and no exception!
Then I returned to my real code (I apologise for Czech characters) - primary key for table poz.JPV is "CONSTRAINT "PK_JPV" PRIMARY KEY ("IdParcely" , "Kod" )", Npgsql driver is
2.2.3.0:
int PočetZprac;
using (NpgsqlCommand CmdInsPar = new NpgsqlCommand("insert into poz.\"JPV\" (\"IdParcely\",\"Kod\") values(:aIdParcely, :aKod)", connPg, transPg)) {
using (SqlCommand CmdParCnt = new SqlCommand("select count(*) from m_parcely_JPV", connMs)) {
ts_ProgressBar.Maximum = PočetZprac = Convert.ToInt32(CmdParCnt.ExecuteScalar());
}
using (SqlCommand CmdPar = new SqlCommand("SELECT distinct ID_PARCELY,TYPRAV_KOD FROM m_parcely_JPV", connMs)) {
using (SqlDataReader RdrPar = CmdPar.ExecuteReader()) {
int i = 0;
while (RdrPar.Read()) {
int IdParcely;
if (Parcely.TryGetValue(Convert.ToInt64(RdrPar["ID_PARCELY"]), out IdParcely)) {
CmdInsPar.Parameters.AddWithValue("aIdParcely", IdParcely);
CmdInsPar.Parameters.AddWithValue("aKod", Convert.ToInt32(RdrPar["TYPRAV_KOD"]));
int počet = CmdInsPar.ExecuteNonQuery();
}
i++;
}
}
}
}
first iteration performs OK, second iteration throws "duplicate key value violates unique constraint "PK_JPV"" exception. (CmdInsPar.Parameters contains 4 items at this moment).
Therefore I rewrote the code to:
int PočetZprac;
using (NpgsqlCommand CmdInsPar = new NpgsqlCommand("insert into poz.\"JPV\" (\"IdParcely\",\"Kod\") values(:aIdParcely, :aKod)", connPg, transPg)) {
CmdInsPar.Parameters.AddWithValue("aIdParcely", -1);
CmdInsPar.Parameters.AddWithValue("aKod", -1);
using (SqlCommand CmdParCnt = new SqlCommand("select count(*) from m_parcely_JPV", connMs)) {
ts_ProgressBar.Maximum = PočetZprac = Convert.ToInt32(CmdParCnt.ExecuteScalar());
}
using (SqlCommand CmdPar = new SqlCommand("SELECT distinct ID_PARCELY,TYPRAV_KOD FROM m_parcely_JPV", connMs)) {
using (SqlDataReader RdrPar = CmdPar.ExecuteReader()) {
int i = 0;
while (RdrPar.Read()) {
int IdParcely;
if (Parcely.TryGetValue(Convert.ToInt64(RdrPar["ID_PARCELY"]), out IdParcely)) {
CmdInsPar.Parameters["aIdParcely"].Value = IdParcely;
CmdInsPar.Parameters["aKod"].Value = Convert.ToInt32(RdrPar["TYPRAV_KOD"]);
int počet = CmdInsPar.ExecuteNonQuery();
}
i++;
}
}
}
}
and now it runs perfectly.
Both Npgsql drivers allow to insert more parameters with the same name (and different value) and maybe there is some minor difference in the way they obtain the parameter value - behavoiur of two Npgsql drivers was slightly different (2.0 retrieved correct values for the second round, 2.2.3 retrieved probably the first values again; but in my simple test (research) code both drivers work well). I never checked the "Parameter.Count" value before, now I see that my (old) approach is very dangerous. ParameterCollection is not like Dictionary<string, object> and therefore duplicities are erratic.
So - thank you Francesco for your effort, do not waste your time, maybe someone can add some code to the Parameters.Add (or Parameters.AddWithValue) code that checks the parameter name and in case of duplicity throws an exception "Why do you populate the same parameter, are you stupid?" - it teaches programers like me to make better and more robust code :-)
Thank you again and I wish you a nice weekend.
Best regards
ID
Dne pátek 13. února 2015 11:52:12 UTC+1 Francisco Figueiredo Jr. napsal(a):