Совет для методов обработки транзакций T-SQL (ADO)? - PullRequest
0 голосов
/ 25 мая 2011

Здесь мы говорим об уровне изоляции, а именно о параллелизме по отношению к локальному серверу Express MSSQL.

Я пытаюсь найти способ начать блокировку данных, когда пользователь решает редактировать строку в GridView -> сохранять данные заблокированными до тех пор, пока он не прекратит редактировать (IE нажал «Обновить»). 1003 *

В виде списка событий это выглядит так:

  1. Пользователь 1 нажимает Редактировать в строке с идентификатором 1.
  2. DataSet (строка) заблокирована, когда пользователь 1 вводит новые данные.
  3. В случае, если пользователь 2 пытается изменить одну и ту же строку, этого пользователя следует заметить еще до того, как он перейдет в режим редактирования в этой строке.
  4. Пользователь 1 обновляет строку, и режим редактирования останавливается, поэтому данные должны быть зафиксированы, а транзакция закрыта.

Я начал делать несколько методов.

До методов мой сервисный метод всегда держит соединение в закрытой / локальной переменной:

private SqlConnection connection = new SqlConnection("Data Source=host\\SQLEXPRESS;Initial Catalog=tablename;User ID=sa;Password=password");

Тогда есть методы.

public SqlTransaction BeginTransaction() {
    //Something like this
    SqlTransaction transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted);
    return transaction;
}

public bool UpdateTidsregistrering(some parameters to be parsed from GUI) {
    using(connection) {
        connection.Open();
        SqlCommand command = connection.CreateCommand();
        //Execute a query here with a try-catch around like normally...
    }
}

public void CloseTransaction() {
    //Close transaction and connection?
}

Мой большой вопрос: это можно правильно использовать?

Ответы [ 3 ]

2 голосов
/ 25 мая 2011

Сценарии, которые нужно учитывать ...
- Кто-то начинает редактировать строку, а потом уходит домой на вечер
- Много разных пользователей, имеющих открытые транзакции из множества разных строк
- Сетевое соединение прерывается, когда пользователь редактирует
- Пользователь A обновляет экран, Пользователь B изменяет и фиксирует строку, Пользователь A начинает изменять строку, не обращая внимания на изменение Пользователя B
- Стоимость проведения нескольких открытых транзакций на нескольких строках
- Стоимость всех пользователей, имеющих постоянно открытые соединения


В общем, я предпочитаю использовать Транзакции только вокруг кода без каких-либо пауз. Особенно паузы создали любое человеческое взаимодействие.

Моя предпочтительная модель для этого сценария - использовать отметку времени «последней модификации».

  1. Обновление данных на экране, удерживая last_modified_time для каждой строки
  2. Пользователь нажимает на строку
  3. Приложение проверяет, изменилось ли last_modified_time этой строки
  4. Если изменено, обновить строку из БД и сообщить пользователю о текущем состоянии
  5. Разрешить пользователю изменять строку на экране
  6. Пользователь нажимает "совершить"
  7. Еще одна проверка, чтобы увидеть, изменилось ли last_modified_time
  8. Если это так, показать разные значения и спросить пользователя, хотят ли они по-прежнему фиксировать. Их изменение
1 голос
/ 25 мая 2011

Не удерживайте транзакцию для этого. Вам потребуется:

  • Открытое соединение
  • Начать транзакцию
  • Выбрать запись для редактирования (= заблокировать запись)
  • Подождите, пока пользователь завершит редактирование
  • Передать изменения
  • Закрыть соединение

Как долго пользователь может редактировать запись? Что произойдет, если пользователь заблокирует записи и отправится на обед? Соединение не должно удерживаться пользователем, а транзакция должна быть максимально короткой. Вся отдельная часть состоит в том, что мы говорим о ASP.NET, где вам придется хранить соединение в сеансе, и если пользователь не фиксирует изменения, соединение будет утечку - у вас скоро закончится соединение.

Это целое может считаться совершенно плохим дизайном и тем, что вы никогда не должны делать!

Добавить новый столбец в вашу таблицу: LockedBy (вы также можете добавить LockedAt). Изменяйте эти столбцы в транзакции только тогда, когда пользователь хочет редактировать запись. Другие пользователи не смогут переключать записи в режим редактирования, когда эти столбцы заполнены. После того, как пользователь внесёт изменения, очистите эти столбцы.

У вас будет одна проблема - вы должны разблокировать записи, если пользователь отменяет изменения, но что если пользователь просто закроет свой браузер? Это потребует некоторой работы, которая будет регулярно запускать и разблокировать записи, заблокированные в течение длительного времени (причина для второго столбца). Вы можете запустить такое задание в агенте SQL.

1 голос
/ 25 мая 2011

В SQL вам нужно:

begin transaction;

select id
from tablename with (updlock, rowlock, holdlock, readpast)
where id = @id;

if @@rowcount = 0
begin
  raiseerror('This record does not exists or is currently locked.',16,1);
  rollback tran;
end;

Пользователь вносит правки здесь ...

update tablename ... ;
commit transaction;

Вы можете легко обернуть это с помощью c #методы для LockRecord / UnlockRecord.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...