2

My app is using HTMLAgilityPack to parse HTML and System.Data.SqlClient to connect with local database and obtain/insert data.

The thing is that sample of code works without any errors:

Database databaseObject = new Database();
List<Account> accounts = new List<Account>();
...
//Add some data to accounts and databaseObject 
...
    databaseObject.Open()
    foreach (Account account in accounts)
    {
        accounts.doMagic(this, databaseObject);
    }

I did not add databaseObject.Close() to be sure that connection with database exists. Allright, now here is code which not works properly:

Database databaseObject = new Database();
List<Account> accounts = new List<Account>();
...
//Add some data to accounts and databaseObject 
...
    databaseObject.Open()
    foreach (Account account in accounts)
    {
        Thread thread = new Thread(() => account.doMagic(this, databaseObject ));
        thread.Start();
    }

this also will not work:

Database databaseObject = new Database();
List<Account> accounts = new List<Account>();
...
//Add some data to accounts and databaseObject 
...
    databaseObject.Open()
        Parallel.ForEach(accounts, account =>
            {
                account.doMagic(this, databaseObject );
            });

It starts to work, but after few seconds I am getting System.InvalidOperationException with information that ExecuteNonQuery requires opened and avaible connection.

What?! Connection should be Opened all the time!

What's more I am getting System.Data.SqlClient.SqlException with info about Timeout Expired

What the hell is going on? I am not closing any connection, so how can it be closed? I can't understand why it is not working properly with implementing a bit multithreading..

3
  • 2
    Don't use the same connection from multiple threads. It will lead to inconsistent state. Open a new connection for each thread. Commented Oct 29, 2016 at 21:40
  • 5
    This is not supposed to sound mean but you don't know the first thing about threading as it seems. It is extremely dangerous to just mark parts of your code multi-threaded without knowing the rules. Threading is quite difficult to get right. Commented Oct 29, 2016 at 21:42
  • 1
    there should be a lock somewhere Commented Oct 29, 2016 at 21:47

1 Answer 1

1

SQLConnection is not a pure managed class, but just a wrapper. Real connection is a COM object with all limitations of COM threading model. Try answer to the simple question: if you use single connection from different threads, in what thread you can catch its exceptions?

The good news is: you can open and close connections in the same or different threads without lost of performance because of connection pooling (actually connection pool can hold connection open). Additionally, connection pool tries to resolve license limitations (limit of contemporary opened connections) and some other issues.

The bad news is: using multiple connections, you face an avalanche of errors in case of some server problems. For such architecture, server connections management is not a trivial case. For many scenarios the most reliable way is to implement a data adapter singleton to encapsulate all client database-related logic.

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

Comments

Your Answer

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