Является ли SqlConnection / SqlCommand потокобезопасным? - PullRequest
5 голосов
/ 06 сентября 2011

В настоящее время я создаю веб-службу WCF.

В качестве части ее работы, к сожалению, потребуется выполнить довольно интенсивные вычисления, однако эти вычисления, к счастью, могут быть разделены между вызовами веб-службы.По сути - нам нужно только выполнить вычисления один раз, и все последующие вызовы могут получить преимущество.

Однако, поскольку WCF не имеет общего состояния приложения, кажется логичным установить WCF в режиме одного экземпляра.(Каждому клиенту потребовались бы некоторые вычисления по всей вероятности, что вынуждает нас пересчитывать их для per-serssion, которые могли бы быть в порядке, или для per-call, которые несостоятельны)

Однако яне очень знаком с защитой кода для нескольких потоков.Я читал об этом кое-что, и поскольку ни один из нашего кода 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

Я посмотрел класс SqlCommand в MSDN: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.aspx, который говорит: «Любая общедоступная статика(Совместно используемые в Visual Basic) члены этого типа являются поточно-ориентированными. Любые члены экземпляра не гарантируют поточно-ориентированные. "

Правильно ли я интерпретирую это, думая, что это означает, что MS не гарантировать, что SqlCommand работает в многопоточном сценарии?

Если это не так, есть ли потокобезопасная альтернатива?

Да, я мог бы просто заблокировать все методы доступа к базе данных в моем веб-сервисе, но а) это ужасно и б) если это не такЯ бы предпочел, чтобы мне не пришлось:)

Заранее спасибо!

Ответы [ 3 ]

9 голосов
/ 06 сентября 2011

Правильно ли я интерпретирую это, думая, что это означает, что MS не гарантирует, что SqlCommand работает в многопоточном сценарии?

Он отлично работает в многопоточном сценарии, если вы правильно его используете.

Если несколько потоков пытаются использовать SAME SqlCommand, что делатьты думаешь произойдет?Как это может работать?

, но если разные потоки, использующие разные соединения, выдают разные команды для одной и той же базы данных, проблем нет.

Замечания о безопасности потоков в MSDN действительно испорчены и плохосформулированы и должны быть написаны кем-то, кто не знал, что такое безопасность потоков .

Что они пытаются сказать этим сообщением (которое прикреплено к 99,9% классови функции, документированные в MSDN), заключается в том, что «Любой статический метод этого типа может безопасно вызываться одновременно несколькими потоками. Любые члены экземпляра в одном и том же экземпляре не гарантированно безопасны при одновременном вызове несколькими потокамино доступ к одному и тому же члену на различных объектах вполне подходит. "

3 голосов
/ 06 сентября 2011

Я не уверен на 100%, что вы пытаетесь сделать одновременно с SqlCommand, но независимо от внутренней безопасности потоков, у вас наверняка будут проблемы исключительно потому, что использование SqlCommand требует от него поддержания состояния, например

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

Если вы пытаетесь поделиться одной и той же командой через несколько потоков, вам придется заблокировать что-то, пока вы ее используете.

Что касается SqlConnection, то он позволяет открывать только один запрос за раз, поэтому, если вы используете DataReaders, вам снова придется что-то блокировать. Использование нескольких соединений / команд необходимо, если вы хотите запустить несколько вещей одновременно.

Я также не уверен, что вы имеете в виду, когда говорите, что у WCF нет общего состояния приложения - это не обязательно верно, это будет зависеть от того, как вы размещаете свое приложение WCF. Если это служба WCF, размещенная в IIS с установленным aspNetCompatibilityEnabled="true", у вас все еще есть объект Application, который вы получите на веб-сайте. Есть и другие варианты, если вы не используете aspNetCompatibility.

2 голосов
/ 06 сентября 2011

просто используйте соединение и команду из одного потока knly и не заботьтесь о проблеме потока уровня приложения на тех.Сервер SQL достаточно хорош для одновременного выполнения операций без необходимости блокировки вашего кода.Также существует пул соединений .Net для быстрого получения действительных соединений.

Я не говорю, что весь создаваемый вами слой WCF не должен заботиться о потоках, но его DAL должен работать, полагаясь на блокировки db, а не блокировки .net.

...