SqlConnection 线程安全吗?

10

我有一个Log类,它将日志记录到Windows日志和SQL表中。为了优化我的代码,我想只使用一个SqlConnection

在MSDN中,它说:任何此类型的public static(Visual Basic中的Shared)成员都是线程安全的。任何实例成员不能保证是线程安全的。

我的问题是:

private static readonly SqlConnection conn = new SqlConnection(ConfigParameters.Instance.UIDConnection);

它是线程安全的吗?如果是,什么时候使用Open()Close()

如果不是,如何正确使用SqlConnection

这是我的完整类代码:

private static readonly SqlConnection conn = new SqlConnection(ConfigParameters.Instance.UIDConnection);

public static long WriteLog(string sSource, string sMessage, int iErrorCode, EventLogEntryType xErrorType)
{
    // Windows Logs
    if (ConfigParameters.Instance.WindowsLog)
        EventLog.WriteEntry(sSource, sMessage, xErrorType, iErrorCode);

    // SQL Logs
    // TODO

    return 0;
}

我找到了这个链接:http://www.codeproject.com/Articles/62249/Connection-Pooling-in-multithreaded-applications。它可能是一个解决方案吗? - BaptX
1
为什么你想要只使用一个连接?这会增加开销以防止线程问题。ADO.NET已经内置了连接池,而且你可以通过将其包装在“using”语句中来最小化给定连接的使用时间。 - Tim
此外,这与WCF无关,因此您可以删除该标签。 - Tim
我选择使用WCF是因为我的Web服务需要连接SQL。但你说得对,我可以将sqlConnection放在对象的实例中。但我担心nb_threads * sqlconnection会占用大量内存。另一方面,如果我只使用静态sqlconnection,事务可能会更长。你认为将SqlConnection放在静态方法中更好吗? - BaptX
1个回答

18

分享 SqlConnection 并不是一种常见的方式,只有在特殊情况下才应该使用。

首先,你说得对,资源池化是一种常用模式,可用于提高使用套接字、网络流、Web 服务等时的性能。

但是,特别是对于 SqlConnection,你不必担心这个问题,因为 .NET Framework 已经为你做好了这个工作,感谢SqlConnection Pool

每当用户在连接上调用 Open 方法时,池化程序都会在池中查找一个可用的连接。如果有可用的池化连接,则返回给调用方,而不是打开新的连接。当应用程序在连接上调用 Close 方法时,池程序将其返回到活动连接的池子中,而不是关闭它。一旦连接被返回到池中,就可以在下一个 Open 调用中重复使用。

你可以把 SqlConnection 视为实际连接的包装器。不要认为实例化新的 SqlConnection 是昂贵的:它不是,很多高流量的网站都是用它构建的。

默认策略(至少对于 SQL Server)是它会自动工作。你只需要注意关闭连接(使用 using 块)。还有许多设置来管理池。

你的代码也包含了一个错误的错误管理:如果连接中止(数据库管理员、网络故障等),你将在日志记录时抛出异常……不理想。

最后,我认为在你的情况下共享 Sql 连接是不合适的。使用异步日志库会更加提高性能。

现在不要过多关注此事,只有当你确信这是一个真正的问题时才需考虑。

我们应该忘记小效率,说起来大约有 97% 的时间:过早的优化是万恶之源,Donald Knuth


我把SqlConnection放在方法里 :) - BaptX

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