Информация об изменениях

Сообщение Re[15]: Блокировки в бизнес-слое от 03.10.2017 10:41

Изменено 03.10.2017 10:42 Sinclair

Re[15]: Блокировки в бизнес-слое
Здравствуйте, Poul_Ko, Вы писали:

P_K>Раз мы прочитали заказы и собираемся их обновлять, то по-хорошему их также нужно блокировать. Чтобы никто другой не мог параллельно изменить / удалить заказ.

В приведённой архитектуре при любом изменении заказа нужно получать блокировки на продукт — ровно по той же причине.
-- внесение изменения в заказ
begin tran -- read_committed
select @old_productId = productId from orders with updlock where id = @order_id -- заранее захватываем U-блокировку, чтобы избежать дедлоков 
set @product1 = min(@old_productId, @new_productId) -- предотвращаем дедлоки, вводя строгую упорядоченность в захвате локов на продукт
set @product2 = max(@old_productId, @new_productId)
sp_getapplock('product_'+@product1)
sp_getapplock('product_'+@product2)

update orders set productId = @new_productId, cost = @new_Cost, ..., where id = @order_id

commit tran

-- удаление заказа
begin tran -- read_committed
select @productId = productId from orders with updlock where id = @order_id -- заранее захватываем U-блокировку, чтобы избежать дедлоков 
sp_getapplock('product_'+@productIf)
delete from orders set productId = @new_productId, cost = @new_Cost, ... where id = @order_id

commit tran


P_K>Речь не об этом. При определённой сложности (в плане количества ветвлений) простая реализация логики в виде одного метода становится невозможной. Получаем ад из ветвлений и всяких флагов... В итоге всё это рефакторится в отдельные классы (например, что-то вроде стратегий), приобретает понятную форму и тестируемость. На хранимых процедурах такой финт невозможен, думаю согласитесь.

Поэтому я вам и говорю про Linq. Он позволяет писать аккуратный и понятный код, который будет транслироваться в корректный SQL без лишних усилий с вашей стороны.
Re[15]: Блокировки в бизнес-слое
Здравствуйте, Poul_Ko, Вы писали:

P_K>Раз мы прочитали заказы и собираемся их обновлять, то по-хорошему их также нужно блокировать. Чтобы никто другой не мог параллельно изменить / удалить заказ.

В приведённой архитектуре при любом изменении заказа нужно получать блокировки на продукт — ровно по той же причине.
-- внесение изменения в заказ
begin tran -- read_committed
select @old_productId = productId from orders with updlock where id = @order_id -- заранее захватываем U-блокировку, чтобы избежать дедлоков 
set @product1 = min(@old_productId, @new_productId) -- предотвращаем дедлоки, вводя строгую упорядоченность в захвате локов на продукт
set @product2 = max(@old_productId, @new_productId)
sp_getapplock('product_'+@product1)
sp_getapplock('product_'+@product2)

update orders set productId = @new_productId, cost = @new_Cost, ..., where id = @order_id

commit tran

-- удаление заказа
begin tran -- read_committed
select @productId = productId from orders with updlock where id = @order_id -- заранее захватываем U-блокировку, чтобы избежать дедлоков 
sp_getapplock('product_'+@productIв)
delete from orders set productId = @new_productId, cost = @new_Cost, ... where id = @order_id

commit tran


P_K>Речь не об этом. При определённой сложности (в плане количества ветвлений) простая реализация логики в виде одного метода становится невозможной. Получаем ад из ветвлений и всяких флагов... В итоге всё это рефакторится в отдельные классы (например, что-то вроде стратегий), приобретает понятную форму и тестируемость. На хранимых процедурах такой финт невозможен, думаю согласитесь.

Поэтому я вам и говорю про Linq. Он позволяет писать аккуратный и понятный код, который будет транслироваться в корректный SQL без лишних усилий с вашей стороны.