TG Telegram Group & Channel
Прусаков Никита про 1С | United States America (US)
Create: Update:

Чтение и запись наборов записей.

В самом начале своей работы как разработчика, неизбежно приходилось сталкиваться с задачами записи регистров сведений. У наборов записей есть методы "Прочитать()", "Записать()". Ну казалось бы все просто. Один метод читает, другой записывает. Да и кому придет в головку читать данные регистра сведений объектной техникой, когда можно прочитать запросом? Но поработав какое-то время, понял, что есть нюансы. Про них и поговорим.

Для начала начнем немного издалека, и поговорим про управляемые блокировки. Кстати, хороший вопрос для собеседования кандидатам: зачем вообще придумали управляемые блокировки ведь раньше (8.1) жили без них и все прекрасно работало. Предлагаю задуматься над этим вопросом. Вернемся к управляемым блокировкам. Они бывают "разделяемые" и "исключительные". "Разделяемые" - совместимы между собой (можно читать в двух параллельных транзакциях), "Исключительные" - не совместимы с друг с другом, а также с разделяемыми.

Также важно понимать, что управляемые блокировки могут быть установлены только в рамках транзакции, и держаться всегда до конца транзакции (в отличии от блокировок СУБД в определенных режимах изоляции).

Вернемся же к регистрам. Когда мы читаем данные методом набора записей "Прочитать()", сервер 1С неявно накладывает управляемую разделяемую блокировку на прочитанные данные. Поясню на примере:

Если регистр сведений "ОсновнойДоговорКонтрагента", с измерением "Контрагент", и ресурсом "Договор". В момент чтения, будет наложена управляемая разделяемая блокировка.

НаборЗаписей = РегистрыСведений.ОсновнойДоговорКонтрагента.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Контрагент.Установить(Контрагент);
НаборЗаписей.Прочитать();

В каких же случаях нам может потребоваться накладывать разделяемую управляемую блокировку? Тут необходимо познакомиться еще с одним термином, который называется "Ответственное чтение". Что это такое?

Ответственное чтение
- это чтение, при котором мы на 100% должны быть уверены, что после прочтения данные не изменятся. В нашем примере если у меня есть алгоритм, который производит действия с основным договором (например получает основной договор контрагента, получает его сумму и отправляет на почту ответственному сотруднику информацию по остатку лимита основного договора), то в процессе выполнения рассылки, другой сотрудник может зайти и поменять основной договор в регистре. В таком случае будут отправлены некорректные данные.

Значит перед рассылкой нам нужно позаботится о том, чтобы данные которые мы прочитали не были изменены. Это можно сделать либо через чтение в объектной технике, либо через установку явной управляемой блокировки через метод "БлокировкаДанных".

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

НаборЗаписей = РегистрыСведений.ОсновнойДоговорКонтрагента.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Контрагент.Установить(Контрагент);
НаборЗаписей.Прочитать();
НаборЗаписей.Очистить();

// код по добавлению строк в набор записей

НаборЗаписей.Записать();

Как вы думаете какая проблема в коде выше 👆? А проблема в том, что данный код может вызвать взаимоблокировку по причине недостаточного уровня блокировки ресурса. Мы сначала читаем, а затем пишем. И если в двух параллельных сеансах попытаться поменять основной договор, то можем словить взаимоблокировку. Эти строчки абсолютно не нужны в данном примере:

НаборЗаписей.Прочитать();
НаборЗаписей.Очистить();


Набор и так будет перезаписан, читать и очищать его не нужно. Поэтому более правильно тут будет сразу записать набор:

НаборЗаписей = РегистрыСведений.ОсновнойДоговорКонтрагента.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Контрагент.Установить(Контрагент);

// код по добавлению строк в набор записей

НаборЗаписей.Записать();

Если было интересно ставьте 🔥 буду делать больше технических постов.

Чтение и запись наборов записей.

В самом начале своей работы как разработчика, неизбежно приходилось сталкиваться с задачами записи регистров сведений. У наборов записей есть методы "Прочитать()", "Записать()". Ну казалось бы все просто. Один метод читает, другой записывает. Да и кому придет в головку читать данные регистра сведений объектной техникой, когда можно прочитать запросом? Но поработав какое-то время, понял, что есть нюансы. Про них и поговорим.

Для начала начнем немного издалека, и поговорим про управляемые блокировки. Кстати, хороший вопрос для собеседования кандидатам: зачем вообще придумали управляемые блокировки ведь раньше (8.1) жили без них и все прекрасно работало. Предлагаю задуматься над этим вопросом. Вернемся к управляемым блокировкам. Они бывают "разделяемые" и "исключительные". "Разделяемые" - совместимы между собой (можно читать в двух параллельных транзакциях), "Исключительные" - не совместимы с друг с другом, а также с разделяемыми.

Также важно понимать, что управляемые блокировки могут быть установлены только в рамках транзакции, и держаться всегда до конца транзакции (в отличии от блокировок СУБД в определенных режимах изоляции).

Вернемся же к регистрам. Когда мы читаем данные методом набора записей "Прочитать()", сервер 1С неявно накладывает управляемую разделяемую блокировку на прочитанные данные. Поясню на примере:

Если регистр сведений "ОсновнойДоговорКонтрагента", с измерением "Контрагент", и ресурсом "Договор". В момент чтения, будет наложена управляемая разделяемая блокировка.

НаборЗаписей = РегистрыСведений.ОсновнойДоговорКонтрагента.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Контрагент.Установить(Контрагент);
НаборЗаписей.Прочитать();

В каких же случаях нам может потребоваться накладывать разделяемую управляемую блокировку? Тут необходимо познакомиться еще с одним термином, который называется "Ответственное чтение". Что это такое?

Ответственное чтение
- это чтение, при котором мы на 100% должны быть уверены, что после прочтения данные не изменятся. В нашем примере если у меня есть алгоритм, который производит действия с основным договором (например получает основной договор контрагента, получает его сумму и отправляет на почту ответственному сотруднику информацию по остатку лимита основного договора), то в процессе выполнения рассылки, другой сотрудник может зайти и поменять основной договор в регистре. В таком случае будут отправлены некорректные данные.

Значит перед рассылкой нам нужно позаботится о том, чтобы данные которые мы прочитали не были изменены. Это можно сделать либо через чтение в объектной технике, либо через установку явной управляемой блокировки через метод "БлокировкаДанных".

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

НаборЗаписей = РегистрыСведений.ОсновнойДоговорКонтрагента.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Контрагент.Установить(Контрагент);
НаборЗаписей.Прочитать();
НаборЗаписей.Очистить();

// код по добавлению строк в набор записей

НаборЗаписей.Записать();

Как вы думаете какая проблема в коде выше 👆? А проблема в том, что данный код может вызвать взаимоблокировку по причине недостаточного уровня блокировки ресурса. Мы сначала читаем, а затем пишем. И если в двух параллельных сеансах попытаться поменять основной договор, то можем словить взаимоблокировку. Эти строчки абсолютно не нужны в данном примере:

НаборЗаписей.Прочитать();
НаборЗаписей.Очистить();


Набор и так будет перезаписан, читать и очищать его не нужно. Поэтому более правильно тут будет сразу записать набор:

НаборЗаписей = РегистрыСведений.ОсновнойДоговорКонтрагента.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Контрагент.Установить(Контрагент);

// код по добавлению строк в набор записей

НаборЗаписей.Записать();

Если было интересно ставьте 🔥 буду делать больше технических постов.
🔥40👍5


>>Click here to continue<<

Прусаков Никита про 1С




Share with your best friend
VIEW MORE

United States America Popular Telegram Group (US)