实现多线程后与数据库的连接丢失
本文关键字:连接 数据库 多线程 实现 | 更新日期: 2023-09-27 18:15:27
我的应用程序使用HTMLAgilityPack
解析HTML
和System.Data.SqlClient
与本地数据库连接并获取/插入数据
问题是代码示例没有任何错误:
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);
}
我没有添加databaseObject.Close()
以确保与数据库的连接存在。好了,下面是不能正常工作的代码:
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也将不起作用:
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 );
});
它开始工作,但几秒钟后,我得到System.InvalidOperationException
的信息,ExecuteNonQuery
需要打开和可用的连接。
什么? !连接应该一直处于打开状态!
更重要的是,我得到System.Data.SqlClient.SqlException
与Timeout Expired
的信息
这到底是怎么回事?我没有关闭任何连接,那么它是如何关闭的呢?我不明白为什么它不能正常工作与实现一点多线程…
SQLConnection不是一个纯托管类,而只是一个包装器。实连接是一个COM对象,具有COM线程模型的所有限制。试着回答这个简单的问题:如果您使用来自不同线程的单个连接,在哪个线程中可以捕获其异常?
好消息是:您可以在相同或不同的线程中打开和关闭连接,而不会因为连接池而损失性能(实际上连接池可以保持连接打开)。此外,连接池试图解决许可证限制(当前打开的连接的限制)和一些其他问题。
坏消息是:使用多个连接,在某些服务器问题的情况下,您将面临大量错误。对于这样的体系结构,服务器连接管理不是一件小事。对于许多场景,最可靠的方法是实现数据适配器单例来封装所有客户端数据库相关的逻辑。