В процессе разработки на платформе 1С:Предприятие программисты часто сталкиваются с ситуацией, когда программный код кажется абсолютно логичным и правильным, но данные в базе данных не обновляются. Типичный пример — попытка изменить значение реквизита в независимом регистре сведений с помощью объекта МенеджерЗаписи, когда в режиме отладки мы видим присвоение значения, но после выполнения метода Записать() в регистре остаются старые данные или значение по умолчанию.
В этой статье мы подробно разберем, почему так происходит, проанализируем типичные ошибки и рассмотрим наиболее надежные способы записи данных в регистры сведений.
Рассмотрим пример кода, который часто становится источником проблем при работе в обычных формах (событие ПриИзменении флажка в табличном поле):
Процедура таблКонтрольРасчетовПриИзмененииФлажка(Элемент, Колонка)
МенеджерЗаписи = РегистрыСведений.КонтрольРасчетов_Этран.СоздатьМенеджерЗаписи();
МенеджерЗаписи.ИдентификаторДокумента = ЭлементыФормы.таблКонтрольРасчетов.ТекущиеДанные.ИдентификаторДокумента;
МенеджерЗаписи.Прочитать();
Если ЭлементыФормы.таблКонтрольРасчетов.ТекущиеДанные.НеПеревыставляемыеРасходы Тогда
МенеджерЗаписи.Проводка = Истина;
Иначе
МенеджерЗаписи.Проводка = Ложь;
КонецЕсли;
МенеджерЗаписи.Записать();
КонецПроцедуры
На первый взгляд, алгоритм прост: создаем объект, устанавливаем ключевое измерение ИдентификаторДокумента, считываем существующую запись, меняем ресурс Проводка и записываем обратно. Однако именно здесь могут скрываться "подводные камни".
Проанализируем работу метода Прочитать(). Для того чтобы МенеджерЗаписи мог однозначно идентифицировать строку в таблице базы данных, необходимо заполнить все измерения, входящие в уникальный ключ записи. Если у регистра КонтрольРасчетов_Этран есть другие измерения (например, Организация, Период для периодических регистров или другие аналитические разрезы), а в коде указан только ИдентификаторДокумента, метод Прочитать() не найдет существующую запись или найдет не ту.
Важный момент: если вы не заполните все измерения перед вызовом Записать(), система может попытаться создать новую запись с пустыми значениями остальных измерений вместо обновления существующей. Если такая запись уже существует (с пустыми полями), возникнет конфликт или перезапись "пустышки", при этом исходная запись останется нетронутой.
Выясним, как взаимодействуют программная запись и интерфейс. Если таблица на форме таблКонтрольРасчетов связана с набором записей этого же регистра, возникает конфликт "двух источников".
МенеджерЗаписи.ТекущиеДанные).В таких случаях правильнее менять значение непосредственно в объекте, к которому привязана форма, например, через ЭлементыФормы.таблКонтрольРасчетов.ТекущиеДанные.Проводка = Истина;, позволяя платформе самой зафиксировать изменения стандартными механизмами.
Многие опытные разработчики рекомендуют отказаться от МенеджерЗаписи в пользу объекта НаборЗаписей. Это позволяет более гибко управлять процессом записи и четко ограничивать область изменений с помощью фильтров (отборов).
Рассмотрим по шагам, как реализовать это правильно:
Набор = РегистрыСведений.КонтрольРасчетов_Этран.СоздатьНаборЗаписей();
// Устанавливаем фильтр по ключевым измерениям
Набор.Отбор.ИдентификаторДокумента.Установить(ЭлементыФормы.таблКонтрольРасчетов.ТекущиеДанные.ИдентификаторДокумента);
Набор.Прочитать();
Если Набор.Количество() > 0 Тогда
// Если запись найдена, правим ее
Запись = Набор[0];
Запись.Проводка = ЭлементыФормы.таблКонтрольРасчетов.ТекущиеДанные.НеПеревыставляемыеРасходы;
Набор.Записать();
Иначе
// Если запись не найдена, можно создать новую (если это необходимо по логике)
НоваяЗапись = Набор.Добавить();
НоваяЗапись.ИдентификаторДокумента = ЭлементыФормы.таблКонтрольРасчетов.ТекущиеДанные.ИдентификаторДокумента;
НоваяЗапись.Проводка = ЭлементыФормы.таблКонтрольРасчетов.ТекущиеДанные.НеПеревыставляемыеРасходы;
Набор.Записать();
КонецЕсли;
Использование НаборЗаписей гарантирует, что вы работаете именно с тем подмножеством данных, которое соответствует вашему фильтру.
Если в отладчике вы видите, что значение МенеджерЗаписи.Проводка = Истина сохраняется вплоть до строки Записать(), но после записи превращается в Ложь, необходимо проанализировать модуль набора записей самого регистра или подписки на события.
Разберем ситуацию: при вызове метода Записать() система инициирует событие ПередЗаписью. В этом событии может содержаться код, который:
Отказ = Истина, из-за чего запись физически не попадает в базу (хотя менеджер записи в памяти может делать вид, что всё успешно).Совет: установите точку останова в процедуре ПередЗаписью в модуле набора записей регистра КонтрольРасчетов_Этран и пройдите процесс записи пошагово.
В исходном коде автора используется МенеджерЗаписи.Прочитать(). В контексте записи одного значения в независимый регистр это не всегда обязательно, но и не является ошибкой. Однако стоит помнить: если ваша цель — просто "задавить" старое значение новым, вы можете просто создать менеджер, заполнить все измерения, установить ресурсы и нажать Записать(). Метод Записать() по умолчанию работает в режиме замещения (если не указан параметр Ложь).
Для гарантированного решения проблемы выполните следующие действия:
1. Проверьте структуру регистра. Убедитесь, что вы заполняете ВСЕ измерения регистра перед вызовом записи.
2. Используйте отладку в модулях. Обязательно проверьте процедуры ПередЗаписью и ПриЗаписи в модуле регистра.
3. Перейдите на НаборЗаписей. Это снимет множество вопросов, связанных с частичным заполнением объекта.
4. Проверьте тип данных. Убедитесь, что реквизит Проводка имеет тип Булево и ему присваиваются именно значения Истина или Ложь, а не результаты неопределенных выражений.
Следуя этим шагам, вы сможете локализовать причину "магического" исчезновения данных и обеспечить стабильную работу механизмов записи в вашей конфигурации.