Блокировка sql в приложении Silverlight - PullRequest
0 голосов
/ 16 апреля 2010

Я не уверен, что это правильный термин, но это то, что я хотел бы сделать: У меня есть приложение, которое использует базу данных mssql. Это приложение может работать в 3 режимах. режим 1) пользователь не изменяет, а только читает базу данных режим 2) пользователь может добавлять строки (по одной за раз) в таблицу в базе данных режим 3) пользователь может изменять несколько таблиц в базе данных (по одному человеку за раз)

вопрос 1) как я могу гарантировать, что, когда пользователь в режиме 3 «заблокирует» базу данных, и все зарегистрированные пользователи, работающие в режиме 2 или режиме 3, не смогут изменить базу данных, пока он не завершит работу? вопрос 2) как я могу гарантировать, что, хотя в режиме 2 есть несколько пользователей, что не будет никакого конфликта, пока они все обновят таблицу? мое предположение здесь состоит в том, что перед добавлением новой строки вы делаете запрос к серверу для текущих уникальных ключей таблицы и добавляете новую запись. это будет достаточно безопасно, хотя?

Спасибо

Ответы [ 3 ]

1 голос
/ 07 июня 2012

Чтобы избежать того, что пользователь делает ненужные (изменения, потому что ему это не разрешено в это время), нужно делать пессимистическую блокировку.

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

Silverlight и сервисная связь асинхронны, и нужно было бы поместить открытую транзакцию в Session или подобное;а также нужно было бы использовать какой-то пул, потому что невозможно открыть бесконечные соединения с базой данных.

Существует другой подход к пессимистической блокировке, не транзакция, а использование таблицы, в которой вы пишете«locktoken» (некоторая информация о том, какая таблица и строка заблокированы), которую приложение может использовать, чтобы уведомить другого пользователя, который пытается выбрать эти данные для редактирования, о том, что они уже редактируются.

Проблема с удалением блокировкижестко так же, как при использовании подхода транзакций.

0 голосов
/ 24 марта 2011

Если вы использовали службы WCF RIA, вы можете решить эту проблему, применив иной подход к проблеме, а не блокируя заранее: если пользователь собирается зафиксировать изменения, которые отличаются от того, что находится в базе данных с момента открытия данные в их форме вы будете информировать их о конфликте (-ах) и дать им возможность принять или отклонить изменения частично или полностью. Это связано с тем, что RIA Services дает вам возможность иметь наборы изменений до того, как вы отправите изменения на сервер.

У Яцина Кхаммала из Pluralsight есть фантастическая демонстрация этого в игре здесь (paywall, но лучшие $ 29, которые я когда-либо тратил). Смотрите видео под названием «Демонстрация: обработка ошибок проверки и параллелизма».

0 голосов
/ 16 апреля 2010

Существует множество способов приблизиться к № 1. Если предположить, что ваши требования верны (я бы хотя бы дважды проверил их, потому что они звучат странно), то, вероятно, я бы сделал, чтобы создать таблицу ApplicationLock, которая выглядит примерно так:

CREATE TABLE ApplicationLock (SessionId UniqueIdentifier, CreateDate DateTime, LockType int, активный бит)

Затем, прежде чем вы захотите сделать что-то, что требует блокировки, проверьте, есть ли активная блокировка такого рода, которая помешает вам делать то, что вы хотите. (И если есть, посмотрите, прошел ли он определенный период времени ожидания. Если он был больше, чем какой-то период времени ожидания, вы сможете снять блокировку.) Если нет блокировки, которая блокировала бы вас, вставьте вашу собственную блокировку (вы можете создать SessionId на клиенте Silverlight с помощью Guid.NewGuid ()), сделать то, что вам нужно, и затем снять блокировку. Если все это может произойти в одном вызове метода веб-службы, вы должны обязательно обернуть его в транзакции, чтобы он автоматически откатывал блокировку в случае сбоя.

Ключ гарантирует, что ваши замки будут очищены. Если блокировка требуется только для одного вызова метода WCF, вы должны быть в состоянии обработать ее в коде на стороне сервера довольно легко. Однако, если они должны сохраняться при вызове методов, я думаю, вам понадобится стратегия, состоящая из нескольких частей. Если вы используете привязки с установлением соединения в своей службе WCF (например, Net.TCP), вы можете обработать событие отключения клиента, что позволит вам автоматически очистить любые блокировки, которые они открыли. Тем не менее, я бы не зависел от этого, и у меня был бы некоторый тайм-аут в качестве запасного варианта.

Для # 2 (предотвращение конфликтов, когда несколько человек редактируют таблицу), это зависит от того, какие конфликты будут проблематичными на бизнес-уровне. Если вы просто беспокоитесь о вставке двух строк, имеющих один и тот же первичный ключ, есть простые способы обойти это. Предполагая, что у вас есть суррогатный ключ в качестве вашего PK, вы должны сделать этот суррогатный ключ либо UniqueIdentifier (например, GUID, который позволяет вам безопасно создать ключ на клиенте), либо вы можете сделать его int / идентификатор столбца , а затем получить значение из таблицы, используя SCOPE_IDENTITY (). Я предпочитаю GUID, но любой из них будет работать.

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

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

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