多线程应用程序中的连接池
介绍在 C# 中处理连接对象和连接池的设计方法。
引言
本文讨论了为执行数据库操作的多线程应用程序开发设计方法。在开发多线程数据库应用程序时,我们总是会挠头回答(或试图回答)一些棘手的问题,例如:
- 谁应该创建连接对象?
- 连接对象应该是业务对象的一个属性吗?还是应该作为一个工具来使用?
- 如何处理事务操作?
- 谁应该释放连接对象?
看起来,关于“七个 W”的智慧(Who, What, Where, When, Why, How, and Whom)在我们脑海中制造了足够的噪音。我找到了回答这些问题的方法,并在这里与您分享。我尝试了两种方法,它们将在下面进行描述。
单个连接对象,多个事务对象
我使用了单例设计模式来确保只创建一个连接对象。同一个连接对象在多个线程之间共享。现在,每个线程都负责处理事务。每个线程都会创建自己的事务对象,并将其传递给它将要执行的所有命令。因此,线程应该维护自己的提交和回滚策略。这样,单个连接可以同时执行多个事务,完全由调用线程管理。
由于数据库不支持并发事务,请确保处理连接打开和事务创建的代码块在锁定机制下执行。因此,在这种方法中,尽管我们可以使用同一个连接对象,但我们必须确保代码是线程安全的(使用锁)。
优点
- 实现了单例,在多个调用线程之间共享一个连接对象。
- 无需释放连接对象(但必须调用 close 方法)。
缺点
- 不使用连接池功能,因为只创建一个连接对象并使用。
- 执行时间增加,因为命令必须使用同一个连接对象执行。
这是单例方法的框图
多个连接对象
多个连接方法略有不同。这种方法将连接对象控制权交给了调用代码。调用代码负责使用和释放连接对象。在理想情况下,调用代码(业务层)不应持有连接对象的引用。它应该在需要时请求连接对象,并使用它,如果需要,将其传递给其子例程。因此,连接对象在一个方法中打开,并在同一个方法中关闭。伪代码将如下所示:
Method ()
{
- Create local connection object, open it
- Do transaction with database.
- Pass connection object to other methods called from this.
- Commit or rollback transaction
- Close connection, dispose it
}
这种方法允许我们创建多个连接对象并并行执行它们。但是,它也强制执行一些条件,例如:
- 调用代码应拥有连接对象的所有权。
- 调用代码应通过在连接字符串中声明来处理连接池。
- 由于可能同时打开多个连接,因此调用代码必须维护连接与其事务之间的关系。
优点
- 使用连接池同时创建多个连接。
- 比单例快,因为多个连接将执行自己的事务。
缺点
- 需要确保正确释放连接对象。
- 连接对象需要通过方法传递。
这是多个连接方法的框图
就是这样。我已经尽力提出了最好的方法。希望您觉得这篇文章很有趣。欢迎反馈。玩得开心...
使用代码
您可以参考附带的源代码文件,以了解更多关于上述方法的细节。
关注点
调试技巧:使用 SQL Server Management Studio Activity Monitor 来查找连接和事务的数量。
类似地,您可以使用以下数据库查询来查找每个数据库的活动连接对象。
查找附加的 *Scripts.txt* 文件以创建所需的数据库。请确保您已将源代码中的默认连接字符串替换为您自己的连接字符串。
历史
- 版本 0:起草初稿。