SqlConnection / SqlCommand 线程安全吗?
我目前正在创建 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
}
END EDIT
我在 MSDN 上查找了 SqlCommand 类: http://msdn.microsoft.com/en-us /library/system.data.sqlclient.sqlcommand.aspx 其中表示:“此类型的任何公共静态(在 Visual Basic 中为共享)成员都是线程安全的。不保证任何实例成员都是线程安全的。”
我是否正确地解释了这一点,认为这意味着 MS 不保证 SqlCommand 在多线程场景中工作?
如果没有,是否有线程安全的替代方案?
是的,我可以锁定我的网络服务中的所有数据库访问方法,但是a)它很难看,b)如果没有必要,我希望我不必这样做:)
提前干杯!
I am currently creating a WCF web service.
As part of its job, it will unfortunately need to do some fairly intensive computations, however these computations can fortunately be shared between calls to the webservice. In effect - we only need to do the computations once, and all later calls can get the benefit.
However, since WCF has no shared application state it seems logical to set WCF in single-instance mode. (Each client would require some of the computations in all likelyhood, forcing us to recompute them per-serssion which could be ok, or per-call which is untenable)
However, I am not very familiar with securing code for multiple threads.
I have been reading up on it some, and as none of our WCF code writes to shared state (other than the computation-bit, which is easy to protect) I'm almost convinced I don't need to change anything.
There is a single snag, though - we use SqlConnection and SqlCommand to communicate with our backend, and I am not sure if I can count on these being thread safe?
EDIT: I should perhaps clarify that the Commands / Connections are always local to a method. We're talking a pattern in the vein of:
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
}
END EDIT
I looked up the SqlCommand class on MSDN:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.aspx
which says: "Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe."
Am I interpreting this correctly in thinking it means that MS does not guarantee that SqlCommand works in a multi threaded scenario?
If it does not, is there a thread-safe alternative?
Yes, I could just lock all database access methods in my webservice, but a) it's ugly and b) if it's not necessary I'd prefer I didn't have to :)
Cheers in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
只要正确使用,它在多线程场景下工作得很好。
如果多个线程尝试使用SAME SqlCommand,您认为会发生什么?怎么可能行得通呢?
但如果使用不同连接的不同线程向同一个数据库发出不同的命令,则没有问题。
MSDN 上关于线程安全的注释确实很破烂,而且措辞也很糟糕,而且一定是由不知道线程安全是什么的人写的。
他们试图通过该消息(MSDN 上记录的 99.9% 的类和函数)表达的是“这种类型的任何静态方法都可以由多个线程安全地同时调用。任何实例成员如果由多个线程同时调用,则不能保证在同一个实例上是安全的,但是在不同对象上访问同一成员是完全没问题的。”
It works fine in a multi-threaded scenario as long as you use it correctly.
If several threads try to use the SAME SqlCommand, what do you think will happen? How could it possibly work?
but if different threads using different connections issue different commands to the same database, there is no problem.
The notes about thread safety on MSDN are really broken and badly worded, and must be written by someone who didn't know what thread safety is.
What they're trying to say with that message (which is tacked onto 99.9% of the classes and functions documented on MSDN) is that "Any static method of this type can be safely called concurrently by multiple threads. Any instance members on the same instance is not guaranteed to be safe if invoked concurrently by multiple threads, but accessing the same member on different objects is perfectly fine."
我不是 100% 确定您尝试与 SqlCommand 同时执行什么操作,但无论内部线程安全如何,您肯定会遇到问题,纯粹是因为使用 SqlCommand 需要它维护状态,例如,
如果您尝试通过多个线程共享同一个命令,您必须在使用某些东西时锁定它。
就 SqlConnection 而言,它只允许您一次打开一个查询,因此如果您使用 DataReaders,则必须再次锁定某些内容。如果您想同时运行多个任务,则使用多个连接/命令至关重要。
当您说 WCF 没有共享应用程序状态时,我也不确定您的意思 - 这不一定是真的,这取决于您托管 WCF 应用程序的方式。如果它是在 IIS 下托管并设置了
aspNetCompatibilityEnabled="true"
的 WCF 服务,您仍然拥有在网站中获得的 Application 对象。如果您不使用 aspNetCompatibility,还有其他选项。I'm not 100% sure what you're trying to do simultaneously with SqlCommand, but whatever the internal thread-safety, you'll surely have problems purely because using the SqlCommand requires it to maintain state, e.g.
If you're trying to share the same command through multiple threads, you'd have to lock something while you were using it.
As far as SqlConnection goes, it will only allow you to have a single query open at a time, so if you're using DataReaders, you'd again have to lock something. Using multiple connections/commands is essential if you want to run multiple things the same time.
I'm also not sure what you mean when you say WCF has no shared application state - this is not necessarily true, it will depend on how you are hosting your WCF application. If it is a WCF service hosted under IIS with
aspNetCompatibilityEnabled="true"
set, you still have the Application object you would get in a web site. There are other options if you're not using aspNetCompatibility as well.只需使用来自 knly 一个线程的连接和命令,而不关心这些线程上的应用程序级别线程问题。 sql server 足以为您处理并发性,无需锁定您的代码。 .Net 连接池也可以快速检索有效连接。
我并不是说您创建的整个 WCF 层不应该关心线程,但它的 DAL 必须依赖数据库锁而不是 .net 锁来工作。
just use connection and command from knly one thread and dont care of app level thread issue on those. sql server is good enough to handle concurrency for you with no need to lock in your code. .Net connection pool is also there to retrieve valid connections fast.
I am not saying the whole WCF layer you make should not care of threads, but its DAL has to work relying on db locks not .net locks.