C# SqlConnection/SqlCommand是线程安全的吗?

C# SqlConnection/SqlCommand是线程安全的吗?,c#,multithreading,locking,thread-safety,sqlcommand,C#,Multithreading,Locking,Thread Safety,Sqlcommand,我目前正在创建一个WCF web服务 不幸的是,作为其工作的一部分,它需要进行一些相当密集的计算,然而幸运的是,这些计算可以在对Web服务的调用之间共享。实际上,我们只需要做一次计算,所有以后的调用都可以得到好处 然而,由于WCF没有共享的应用程序状态,所以在单实例模式下设置WCF似乎是合乎逻辑的。(每个客户都可能需要一些计算,迫使我们在每次服务中重新计算,这可能是正常的,或者在每次调用中重新计算是不可行的) 但是,我不太熟悉多线程的安全代码。 我已经读了一些,由于我们的WCF代码没有写入共享状

我目前正在创建一个WCF web服务

不幸的是,作为其工作的一部分,它需要进行一些相当密集的计算,然而幸运的是,这些计算可以在对Web服务的调用之间共享。实际上,我们只需要做一次计算,所有以后的调用都可以得到好处

然而,由于WCF没有共享的应用程序状态,所以在单实例模式下设置WCF似乎是合乎逻辑的。(每个客户都可能需要一些计算,迫使我们在每次服务中重新计算,这可能是正常的,或者在每次调用中重新计算是不可行的)

但是,我不太熟悉多线程的安全代码。 我已经读了一些,由于我们的WCF代码没有写入共享状态(除了易于保护的计算位),我几乎确信我不需要更改任何内容

不过,有一个单一的障碍——我们使用SqlConnection和SqlCommand与后端通信,我不确定这些是否是线程安全的

编辑:我也许应该澄清一下,命令/连接对于一个方法来说总是本地的。我们讨论的模式是:

using sqlConn = new SqlConnection(...) {
 try {
  sqlConn.Open()
} catch () {
  throw new FaultException();
}
var cmd = new SqlCommand("Some SQL", sqlConn);
var reader = cmd.ExecuteReader();
//Read the stuff 
reader.Close();
//Return something
}
结束编辑

我在MSDN上查找了SqlCommand类: 上面说:“这种类型的任何公共静态(在Visual Basic中共享)成员都是线程安全的。任何实例成员都不能保证是线程安全的。”

我是否正确地解释了这一点,认为这意味着MS不能保证SqlCommand在多线程场景中工作

如果没有,是否有线程安全的替代方案

是的,我可以锁定我的Web服务中的所有数据库访问方法,但a)这很难看,b)如果没有必要,我宁愿不必:)


提前干杯

我不能100%确定您试图用SqlCommand同时执行什么操作,但无论内部线程安全如何,您肯定会遇到问题,因为使用SqlCommand需要它维护状态,例如

SqlCommand cmd = myConnection.CreateCommand();
cmd.CommandText = "......";
cmd.Parameters.Add(.....);
cmd.ExecuteNonQuery();
如果您试图通过多个线程共享同一个命令,则必须在使用该命令时锁定它

就SqlConnection而言,它只允许您一次打开一个查询,所以如果您使用的是DataReaders,那么您必须再次锁定某些内容。如果您想同时运行多个程序,则必须使用多个连接/命令


当你说WCF没有共享的应用程序状态时,我也不确定你的意思——这不一定是真的,这将取决于你如何托管你的WCF应用程序。如果它是在IIS下托管的WCF服务,并设置了
aspNetCompatibilityEnabled=“true”
,则您仍然拥有将在网站中获得的应用程序对象。如果您不使用aspNetCompatibility,还有其他选项。

只需使用来自一个线程的连接和命令,而不关心这些线程上的应用程序级线程问题。sql server足以为您处理并发性,而无需锁定代码。Net连接池也用于快速检索有效连接

我并不是说你制作的整个WCF层不应该关心线程,但是它的DAL必须依靠db锁而不是.net锁来工作

我是否正确地解释了这一点,认为这意味着MS不能保证SqlCommand在多线程场景中工作

只要正确使用,它在多线程场景中工作良好

如果多个线程尝试使用同一个SqlCommand,您认为会发生什么情况?怎么可能呢

但是,如果使用不同连接的不同线程向同一个数据库发出不同的命令,则没有问题

MSDN上关于线程安全的注释真的很不完整,措辞也很糟糕,必须由不知道什么是线程安全的人编写


他们试图用这条消息(在MSDN上记录的99.9%的类和函数中都有)来说明的是“这种类型的任何静态方法都可以由多个线程安全地并发调用。如果由多个线程并发调用,则不能保证同一实例上的任何实例成员都是安全的,但是在不同对象上访问同一成员是完全可以的。“

我意识到我的想法不太清楚,所以我只是更新了一个我正在尝试做的事情的例子。。。我不在方法调用之间共享命令/连接。我总是在每个方法中添加新的命令/连接。我不确定的是,它们内部是否有某种结构会咬到我的屁股。不过我不知道aspNetCompatibilityEnabled——谢谢!我非常不确定这种智能的结构方式,有时它真的可以帮助你把东西扔给那些已经做了很久的人:-)如果你不在线程间共享同一个实例,并且类的静态部分是线程安全的,那么你就没有问题了不要在线程间共享这些实例,打开它们,运行查询,并尽快处理。连接池将处理连接优化。同意-使用同一个SqlCommand的多个线程将永远不会工作。我不确定的是,正如您所说,“使用不同连接的不同线程向同一数据库发出不同命令”是否安全。基本上,我怎么知道SqlCommand没有一些疯狂的内部静态状态,这将是一个问题?即使在我写这篇文章的时候,我意识到这听起来有多么愚蠢,然而。。。所以,谢谢你的回答!我的代码应该是OK:-)@jalf。不同的线程发出不同的命令,但使用一个静态单例连接如何?我已经发现这是工作,但怀疑它可能会打破在某些情况下。