2013-06-25 2 views
4

Самый простой способ, чтобы проиллюстрировать мой вопрос с этой C# код:SqlDataReader и доступ к базе данных параллелизм

using (SqlCommand cmd = new SqlCommand("SELECT * FROM [tbl]", connectionString)) 
{ 
    using (SqlDataReader rdr = cmd.ExecuteReader()) 
    { 
     //Somewhere at this point a concurrent thread, 
     //or another process changes the [tbl] table data 

     //Begin reading 
     while (rdr.Read()) 
     { 
      //Process the data 
     } 
    } 
} 

Так что случилось бы с данными rdr в такой ситуации?

+0

Я предполагаю, что вы получаете старые данные. Результаты возвращаются по мере выполнения запроса и хранятся в сетевом буфере на клиенте до тех пор, пока вы не попросите их использовать метод Read DataReader. Но это зависит от уровня изоляции. Посмотрите на этот ответ: http://stackoverflow.com/a/1539005/284240 –

+0

@TimSchmelter: ОК. Спасибо за ссылку, хотя ваш собственный ответ несколько неоднозначен. Вы говорите, что я получу старые данные, но в конце вы говорите, что это зависит от уровня изоляции. Итак, кто это? И что это за «уровень изоляции»? – ahmd0

+0

если бы это был ответ, я бы отредактировал его и удалю первое предложение ;-) –

ответ

2

Я действительно испытал это. Код испытания:

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 не разрешает изменять базовые данные.

+0

Спасибо за выполнение этого теста. Какую версию SQL Server вы запустили? Кроме того, вы можете показать, как вы могли бы обернуть его в «транзакцию»? – ahmd0

+0

@ ahmd0 См. Обновление ... – user1429080

Смежные вопросы