在C#应用程序中如何在多个线程之间共享数据库连接?

8
我发现关于这个话题的信息非常少,希望有人能指导我一些信息和可能的示例代码。

我猜这也因数据库供应商而异...mysql、ms sql、sqlite... - tuinstoel
4个回答

11

一般来说,连接对象不是线程安全的(SqlConnect、MySqlConnection 和 OracleConnection 明确指出它们不是线程安全的)。

不要在多个线程之间共享同一个连接。


6
我认为不要共享连接对象本身,只需创建一个新的连接并让ADO.net处理连接池。

我倾向于同意,数据库服务器被设计用于管理连接池,最好让数据库服务器做它被设计来做的事情。 - Stéphane

3
为了回应问题的实际参数,而不是将其驳回,我会包装 DbCommand 以帮助同步对连接的访问(仅当且仅当您绝对必须这样做时)。
public class SyncedDbCommand : DbCommand
{
    private DbCommand _cmd;
    private object _sync;

    public SyncedDbCommand(DbCommand cmd, object sync)
    {
        _cmd = cmd;
        _sync = sync;
    }

    // omitted basic proxy method overrides

    protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
    {
        Monitor.Enter(_sync);
        return _cmd.ExecuteReader();
    }

    public override int ExecuteNonQuery()
    {
        Monitor.Enter(_sync);
        return _cmd.ExecuteNonQuery();
    }

    public override object ExecuteScalar()
    {
        Monitor.Enter(_sync);
        return _cmd.ExecuteScalar();
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            Monitor.Exit(_sync);
        }
        base.Dispose(disposing);
    }
}

要使用该示例,您必须使用实际的DbCommand实例化它,以及一些在连接的所有用法中共享的对象实例。在最简单的用法中,您甚至可以将连接对象本身作为锁对象传递。实例化应在using语句中发生。这并不免除您了解自己的使用要求以及Monitor类和锁定如何工作的责任。
无论如何,您都希望在线程之间同步连接的用法,上述方法是其中之一。

1
绝对不要这样做,没有任何好的理由去这么做,而且会影响你的应用程序性能。像上面的答案所说,使用连接池。 - Kieran Benton
1
“没有充分的理由”?你怎么能在不了解他代码架构的情况下这样说呢?至于共享连接,这是一种众所周知的方法,可以在不升级到 MSDTC 的情况下启用事务。这是一个巨大的性能优势。尽管如此,从零开始,当然我不会建议采用我回答中描述的方法。但是,在“尊重提问者并回应他问题的细节”方面,这是我的建议。 - G-Wiz

0

没有样例代码是因为(几乎)没有人这样做,因为这是一个非常非常糟糕的想法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接