سؤال

Is it possible to use Npgsql function with Parallel.For block?

Here is my example,but I got exception "Backend sent unrecognized response type: \0"

    NpgsqlConnection PGconnexion = new NpgsqlConnection(...);
    string SqlParallel = "";
    int OID = -1;
    Parallel.For(0, 100, i =>
    {
        SqlParallel = string.Format(@"INSERT INTO ParallelTest(Id) VALUES({0}) RETURNING OID;", i);
        using (NpgsqlCommand PGcommandParallel = new NpgsqlCommand(SqlParallel, PGconnexion)) 
        {
            try { OID = (int)PGcommandParallel.ExecuteScalar(); }
            catch (Exception ex) { Console.WriteLine(ex.Message); }
        }
        Console.WriteLine("Insert: {0} OID: {1}", i, OID);
    });

And PostgreSql table schema

-- Table: paralleltest

-- DROP TABLE paralleltest;

CREATE TABLE paralleltest
(
  id integer
)
WITH (
  OIDS=TRUE
);
GRANT ALL ON TABLE paralleltest TO public;
هل كانت مفيدة؟

المحلول

Christian!

Npgsql, like other providers, aren't thread safe. As you are using multiple threads with the same connection you end up with this problem.

In order to make it work, you have to put the line which creates the connection inside the Parallel.For loop:

    string SqlParallel = "";
    int OID = -1;
    Parallel.For(0, 100, i =>
    {
       using (NpgsqlConnection PGconnexion = new NpgsqlConnection(...))

       {
            SqlParallel = string.Format(@"INSERT INTO ParallelTest(Id) VALUES({0}) RETURNING OID;", i);
            using (NpgsqlCommand PGcommandParallel = new NpgsqlCommand(SqlParallel, PGconnexion))
            {
                 try { OID = (int)PGcommandParallel.ExecuteScalar(); }
                 catch (Exception ex) { Console.WriteLine(ex.Message); }
             }
             Console.WriteLine("Insert: {0} OID: {1}", i, OID);
         } 
     });

I tested it here and it worked ok. Please, give it a try and let me know if you still have an issue with this change. Note that I used the "using" clause so the connection is closed as soon as the block finishes.

I hope it helps.

نصائح أخرى

With the help of Francisco Junior, here thread safe solution.

        Parallel.For(0, 100, i =>
        {
            string SqlParallel = string.Format(@"INSERT INTO ParallelTest(Id) VALUES({0}) RETURNING OID;", i);
            using (NpgsqlConnection PGconnexionParallel = new NpgsqlConnection(string.Format("Server={0};Port={1};User Id={2};Password={3};Database={4};", PGHost, PGPort, PGUser, PGPassword, PGDatabase)))
            {
                PGconnexionParallel.Open();
                using (NpgsqlCommand PGcommandParallel = new NpgsqlCommand(SqlParallel, PGconnexionParallel))
                {
                    try 
                    { 
                        int OID = (int)PGcommandParallel.ExecuteScalar();
                        Console.WriteLine("SqlParallel: {0} OID: {1}", SqlParallel, OID);
                    }
                    catch (Exception ex) { Console.WriteLine(ex.Message); }
                }
            }
        }); 
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top