Я действительно испытал это. Код испытания:
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["test"].ConnectionString))
{
conn.Open();
using (SqlCommand comm = new SqlCommand("select * from test", conn))
{
using (var reader = comm.ExecuteReader())
{
int i = 0;
while (reader.Read())
{
if ((string)reader[1] == "stop")
{
throw new Exception("Stop was found");
}
}
}
}
}
Чтобы проверить, я инициализируется таблицу с некоторыми фиктивные данные (убедившись, что ни одна строка со значением «стоп» не был включен). Затем я поставил точку останова на линии int i = 0;
. Хотя выполнение было остановлено в точке останова, я вставил строку в таблицу со значением «stop».
Результатом было то, что в зависимости от количества начальных строк в таблице Exception
был выброшен/не выброшен. Я не пытался определить, где именно был предел строк. Для десяти строк не было выбрано значение Exception
, то есть читатель не заметил строку, добавленную из другого процесса. С десятью тысячами строк было исключено исключение.
Ответ получен так: Это зависит от модели. Без обертывания команды/чтения внутри Transaction
вы не можете полагаться ни на поведение.
Обязательный отказ от ответственности: Это, как он работал в моем окружении ...
EDIT:
я тестировал с помощью локального сервера Sql на моем Dev машины. Он сообщает себя:
Microsoft SQL Server 2008 R2 (SP1) - 10.50.2550.0 (X64)
Что касается сделок:
Вот код, где я использую транзакцию:
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["test"].ConnectionString))
{
conn.Open();
using (var trans = conn.BeginTransaction())
using (SqlCommand comm = new SqlCommand("select * from test", conn, trans))
{
using (var reader = comm.ExecuteReader())
{
int i = 0;
while (reader.Read())
{
i++;
if ((string)reader[1] == "stop")
{
throw new Exception("Stop was found");
}
}
}
trans.Commit();
}
}
В этом коде я создаю транзакцию без явного указания уровня изоляции. Это обычно означает, что будет использоваться System.Data.IsolationLevel.ReadCommitted
(я думаю, что уровень изоляции по умолчанию может быть установлен в настройках сервера Sql где-то). В этом случае читатель ведет себя так же, как и раньше. Если я его изменю, используйте:
...
using (var trans = conn.BeginTransaction(System.Data.IsolationLevel.Serializable))
...
Вставка записи «стоп» блокируется до тех пор, пока не будет выполнена транзакция. Это означает, что, хотя читатель активен, Sql Server не разрешает изменять базовые данные.
Я предполагаю, что вы получаете старые данные. Результаты возвращаются по мере выполнения запроса и хранятся в сетевом буфере на клиенте до тех пор, пока вы не попросите их использовать метод Read DataReader. Но это зависит от уровня изоляции. Посмотрите на этот ответ: http://stackoverflow.com/a/1539005/284240 –
@TimSchmelter: ОК. Спасибо за ссылку, хотя ваш собственный ответ несколько неоднозначен. Вы говорите, что я получу старые данные, но в конце вы говорите, что это зависит от уровня изоляции. Итак, кто это? И что это за «уровень изоляции»? – ahmd0
если бы это был ответ, я бы отредактировал его и удалю первое предложение ;-) –