2011-09-06 123 views
4

我目前正在创建一个WCF Web服务。SqlConnection/SqlCommand线程安全吗?

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

但是,由于WCF没有共享应用程序状态,因此将WCF设置为单实例模式似乎是合理的。 (每个客户端需要某些计算在所有的情形产生,迫使我们重新计算他​​们每serssion这可能是好的,或者每个调用,它是站不住脚的)

不过,我不是很熟悉的固定码为多个线程。 我一直在读它,并且因为我们的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类: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.aspx 它说:“任何公共静态成员(在Visual Basic中的Shared)这种类型是线程安全的,任何实例成员都不能保证线程安全。“

我是否认为这是正确解释这意味着MS确实而不是保证SqlCommand在多线程场景中工作?

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

是的,我可以只锁定在我的web服务所有的数据库访问方法,但一)它的丑陋和b)如果它没有必要我宁愿我没得:)

干杯提前!

+0

如果您不跨线程共享同一实例,并且类的静态部分是线程安全的,那么您没有问题 –

+1

不要在线程之间共享这些实例,打开它们,运行查询并处理尽快地。连接池将处理连接优化。 – TheCodeKing

回答

8

我是否认为这是正确解释这意味着MS不保证SqlCommand在多线程场景中工作?

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

如果有几个线程试图使用SqlCommand,你认为会发生什么?它怎么可能工作?

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

有关MSDN上线程安全性的注意事项真的很糟糕,措辞也很糟糕,必须由不知道线程安全性的人写的。他们试图用这个消息说的东西(它被添加到MSDN上记录的99.9%的类和函数中)是:“这种类型的任何静态方法都可以安全地由多个线程同时调用。成员在同一实例不保证安全,如果多线程同时调用,但访问同一成员不同对象是完全正常的。“

+0

同意 - 使用SAME SqlCommand的几个线程将永远不会工作。 我不确定的是,如果可以安全地拥有,就像你所说的,“不同的线程使用不同的连接向同一个数据库发出不同的命令”。基本上,我怎么会知道SqlCommand没有一些疯狂的内部静态状态,这将是一个问题?即使在我写这篇文章时,我意识到这听起来有多愚蠢,但是......所以,谢谢你的回答!我的代码应该可以:-) – Fafnr

2

我不是100%确定你想要与SqlCommand同时做什么,但无论内部线程安全,你肯定都会遇到问题,纯粹是因为使用SqlCommand需要它保持状态,

SqlCommand cmd = myConnection.CreateCommand(); 
cmd.CommandText = "......"; 
cmd.Parameters.Add(.....); 
cmd.ExecuteNonQuery(); 

如果你想通过多个线程共享相同的命令,你必须在你用它来锁定一些东西。

就SqlConnection而言,它只允许您一次打开一个查询,因此如果您使用的是DataReaders,则需要再次锁定某些内容。如果你想在同一时间运行多个事物,使用多个连接/命令是很重要的。

当你说WCF没有共享应用程序状态时,我也不确定你的意思 - 这不一定是真实的,它将取决于你如何托管你的WCF应用程序。如果它是一个WCF服务托管在IIS与aspNetCompatibilityEnabled="true"设置,您仍然有应用程序对象,您将在Web站点中。如果您还没有使用aspNetCompatibility,还有其他选项。

+0

我意识到我很不清楚,所以我只是更新了一个我正在尝试做的事情的例子......我不在方法调用之间共享命令/连接。我总是在每种方法中新增命令/连接。我不确定的是,如果他们内部有一些结构会咬我的屁股。 虽然我不知道有关aspNetCompatibilityEnabled - 谢谢!我很不确定这种结构的巧妙方式,有时候它确实可以帮助你将这些东西扔给那些一直在做这些东西的人:-) – Fafnr

2

只使用来自knly一个线程的连接和命令,而不关心那些应用程序级别的线程问题。 SQL服务器足以处理并发性,无需锁定代码。 .Net连接池也可以快速检索有效的连接。

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