Чем отличается набор записей от менеджера записей 1с
В этой статье мы научимся программно работать с регистром сведений, используя объект Менеджер записи регистра сведений.
Создать менеджер регистра сведений достаточно просто, например:
Хочу заметить, что работать с менеджером регистра сведений можно или в толстом клиенте, или в серверном контексте. В тонком клиенте код, написанный в этой статье работать не будет!
Для того, чтобы программным способом создать, редактировать или удалить конкретную запись независимого регистра сведений, необходимо использовать объект РегистрСведенийМенеджерЗаписи. С помощью данного объекта можно получить доступ к записи с необходимым набором полей. Создается менеджер записи с помощью функции менеджера регистров СоздатьМенеджерЗаписи.
Переменная МенеджерЗаписи, которую мы создали, имеет тип РегистрСведенийМенеджерЗаписи, этот тип предназначен для чтения, редактирования и удаления конкретной записи. Мы можем обращаться к измерениям, ресурсам и реквизитам регистра сведений как к свойствам данного объекта. Заполним созданную запись.
Объект РегистрСведенийМенеджерЗаписи позволяет управлять записью регистра сведений и применим только для независимых регистров. Доступ к записи обеспечивается путем присвоения значений полям объекта, которые соответствуют измерениям, ресурсам и реквизитам регистра. В Вашем примере это измерения Период, ВидТоплива и Поставщик, а также ресурс Цена.
Переменные, которые присваиваются полям регистра в моем случае это реквизиты управляемой формы 1С.
Относительно периода замечу, что платформа самостоятельно изменит текущую дату на дату начала периода, который установлен в свойстве периодичность регистра сведений (если периодичность месяц, а в период передана дата 21.12.2017, то запишется 01.12.2017).
В данном примере я не выясняю, есть ли уже запись с заданным набором ключевых полей (измерений), а просто записываю ее, поэтому если такая запись уже есть, то она перезапишется.
Метод Прочитать считывает данные регистра по указанным измерениям и периоду, а метод Выбран возвращает Истину, если есть запись с указанными полями, и Ложь, если такой нет.
В этом случае наш код изменится.
В этом случае мы присваиваем значения ключевым полям (измерениям) и периоду. А после применяем метод Прочитать. Данный метод считывает записи с регистра по указанным ключевым полям (измерениям) и периоду. Если есть записи с данным набором полей, то метод Выбран возвращает Истину, иначе – Ложь. В Вашем примере, если метод Выбран вернул значение Ложь (записей нет), то мы присваиваем значения измерениям и ресурсу и записываем.
Если же нам нужно будет удалить запись с заданным набором измерений, то код немного поменяется.
Отличное пособие по разработке в управляемом приложении 1С, как для начинающих разработчиков, так и для опытных программистов.
- Очень доступный и понятный язык изложения
- Книга посылается на электронную почту в формате PDF. Можно открыть на любом устройстве!
- Поймете идеологию управляемого приложения 1С
- Узнаете, как разрабатывать управляемое приложение;
- Научитесь разрабатывать управляемые формы 1С;
- Сможете работать с основными и нужными элементами управляемых форм
- Программирование под управляемым приложением станет понятным
Если Вам помог этот урок решить какую-нибудь проблему, понравился или оказался полезен, то Вы можете поддержать мой проект, перечислив любую сумму:
можно оплатить вручную:
Есть непереодический независимый регистр в который записываются данные из ТЗ, наполняемой при чтении текстовых файлов логов.
Регистр:
Измерения: Дата(датавремя), ФизЛицо(справочникссылка);
Ресурс: Вес (Число);
Данные снимаются хаотично, т.е. в файле может быть за день 5 взвешиваний одного человека, может одно, может 234. Один человек - один файл, который наполняется дописываением новых данных в конец. Частота обновления лога - неделя (через неделю данные в файле очищаются и он пишется с нуля).
Данные логов пишутся в ТЗ, после чего ТЗ необходимо записать в регистр.
Проблема в том, что регистр уже может содержать часть данных из файла и нужно дописать только новые данные (ТЗ же каждый раз содержит данные файла целиком).
Можно-ли использовать для записи набор и если да -как правильно это сделать?
Назначение и особенности использования менеджера записи регистра сведений
Объект РегистрСведенийМенеджерЗаписи используется для работы с независимыми регистрами сведений (не подчиненными регистратору). Можно сказать, что данный объект является вспомогательным.
Основным объектом, предназначенным для модификации записей регистра сведений, является РегистрСведенийНаборЗаписей. Он позволяет считывать и записывать группы записей, отобранные по значениям измерений и периоду (для периодических регистров сведений). В модуле набора записей имеются обработчики событий, позволяющие контролировать все операции изменения данных регистра.
Объект РегистрСведенийМенеджерЗаписи используется в тех случаях, когда необходимо выполнить операцию только над одной записью. При этом менеджер записи использует для выполнения записи два набора записей, устанавливая им соответствующие значения отборов. Поэтому обработчики событий набора записей вызываются и тогда, когда для записи данных используется менеджер записи.
При редактировании записи в списке регистра сведений система использует именно менеджер записи. На примере редактирования списка видно, что менеджер записей предоставляет разработчику модель манипулирования записями регистра, допускающую корректировку значений измерений. То есть менеджер выполняет удаление записи со старыми значениями измерений и запись с новыми значениями. Именно такая модель выглядит в списке для пользователя как редактирование записи. Таким образом, основное назначение менеджера записи - обеспечить без дополнительных сложностей редактирование отдельных записей в интерактивных режимах.
С точки зрения производительности использование наборов записей будет максимально эффективным. Использование менеджера записей в некоторых случаях будет столь же эффективным, а в некоторых менее, так как будут выполняться лишние действия.
Добрый день. Чем плох менеджер в плане производительности при записи одной или нескольких строк?
При записи нескольких строк плох тем, что не может записать несколько строк.
технически, при записи набора, сервер приложений записывает каждую строку по отдельности - да - так, же, как он делает при записи менеджером записи. Но при записи набора он это делает в одной транзакции. При записи туевой хучи менеджеров будет туева хуча транзакций.
Если не ошибаюсь, внутри там все равно набор записей из одной записи. Так что производительность одинаковая.
Вообще, менеджер хорош тем, что, если руки из жопы, то с его помощью ты весь регистр не угондонишь.
>записывает каждую строку по отдельности Трассировка это подтверждает? Я не проверял, но уверен, что там один INSERT/UPDATE и массив параметров. Насчет транзакций, никто не мешает записывать менеджером записи в одной транзакции.
зато в начале набор одним запросом сначала очищает записи а в транзакцию можно и насильно обернуть
Да, я поторопился с выводами. Если подумать, то в наборе записей всегда есть отбор, поэтому не массив параметров, а WHERE. Но уверенность в том, что не "каждую строку по отдельности", остается. Какой смысл ставить очевидный барьер производительности?
а как будет выглядеть этот запрос, например, при записи набора из 1000 строк?
Смысл в Error: 10739, Severity 15, The number of row value expressions in the INSERT statement exceeds the maximum allowed number of 1000 row values.
РегистрыСведений.КонтактнаяИнформация.СоздатьНаборЗаписей.Записать какой здесь отбор всегда есть?
Здесь отбор на тех, кто свой код тестит на копии и смотрит в результат или не тестит и потом ищет бэкапы.
Для INSERT скорее всего массив параметров. Для UPDATE, DELETE отбор. Если отбор не установлен, значит будет DELETE без отбора, то есть на весь регистр. Я имел в виду, что набор обрабатываемых строк всегда можно идентифицировать отбором.
"Для INSERT скорее всего массив параметров. Для UPDATE, DELETE отбор." ты несешь какую-то дичь
При сохранении информации при использовании в программном коде объекта МенеджерЗаписи Платформа сама создает объект НаборЗаписей, а его уже записывает
я уже писал: 1. один DELETE стирает все старые записи согласно отбора 2. куча INSERT где по одной записи вставляются новые
Если "записать(ложь)", то delete нет, сразу поток insert
Набор круче Менеджера только тем, что Delete делается 1 раз. Вот и все. Толпу менеджеров можно обернуть в НачатьТранзакцию и ваш SDD будет жить спокойной жизнью.
Всем спасибо, за ответы. Я так понял, что мы пришли к единому мнению.
если есть подписки при записи/перед записью, то они в случае наобра также один раз отработают
менеджер работает по одной записи,иногда это очень удобно и блокировка идет только в момент записи,то есть можно избежать столкновения транзакций не всегда хорошо,если одна большая транзакция
Собственно сам никогда менеджер не использую, но зачем-то он же нужен!
чтобы случайно не грохнуть весь регистр менеджер записи всегда работает только с одной записью
малейшая ошибка при установке отбора и набор распространяется на весь регистр. его запись приведёт к затиранию чего-нибудь
согласен это плюс, но ситуация выбора инструментов - минус
Если не знаешь, зачем это нужно, то значит, тебе это не надо.
Что ты от него хочешь? Он до сих пор не разобрался с Неопределено
да я бы не задавал вопросов глубоко философских, если бы не разобрался, то был стёб над 1С
Для разных задач разные инструменты. И это естественно. А вопрос лучше или хуже - в принципе некорректен.
и кстати, для РН отбор возможен только по регистратору, так почему бы не сделать было лаконичное:
на уровне платформы менеджерЗзаписи всё равно работает через НаборЗаписей, так что это просто объект-обёртка для удобства программирования (меньше строк и более понятный синтаксис) и для большей безопасности (чтобы не удалить весь регистр)
В туже копилку, чем Ресурс от Реквизита отличается в РС?
ну ты ещё спроси, чем NULL отличается от Неопределено
Например, для получения значений ресурсов есть методы Получить, ПолучитьПоследнее/Первое
почему выборка это не коллекция и ее нельзя обойти с помощью "Для каждого. "?
Потому что это динамическая выборка (курсор), а не объект в памяти
Почему ЗначениеЗаполнено дает ложь, а ЗначениеЗаполнено(Ложь) дает истину?
Почему занимается 1С, если её ненавидит? Ушёл бы давно в SAP или Axapta
При построении виртуальных таблиц ресурсы учитываются, а реквизиты - нет.
если так, то как ему доступен метод Количество? Там происходит перебор всей выборки?
при вызове метода производится запрос типа Выбрать Количество(*)
лажу ты сказал не скажу пока )) зачет не факт, кстати, надо проверять
Тем и отличается, что один ресурс, другой реквизит. Видимо, задающих вопрос "Почему в регистрах накопления есть реквизиты, а в регистрах сведений нет" гораздо больше, чем интересующихся чем ресурс отличается от реквизита.
Действительно. Если бы в регистрах сведений не было реквизитов, то опять бы затянул свою песню.
+1 А в виртуальных таблицах РС реквизиты все-таки есть, хотя разработчики платформы могли бы этого не делать.
Просто они уже наступали на грабли, когда в виртуальных таблицах нужны реквизиты, а их нет, из-за чего приходится использовать реальную таблицу. и раз их можно безболезненно получить - то почему бы и нет?
При записи записи через менеджер записи все равно происходит запись всего набора :)
но работа в некоторых случаях (когда набор = записи) с записью удобнее и не медленнее
не только. например получить запросом те записи, которые нужно удалить и через менеджер записи ЗаполнитьЗначенияСвойств, Удалить вместо мучительного (условно) заполнения отборов наборов для записи этих самых пустых наборов
но если не обернуть в транзакцию, то при ошибке НЗ откатит все удаления, цикл МЗ просто в середине прервется и откати только одну
Ты попробуй записать набором записи с видом сравнения отбора "В списке", тогда поймешь, чем плох набор записей.
Ну вот актуальный пример. Проведение документа Табель учета рабочего времени по регистру Графики работы по видам времени. Там график - это ссылка на справочник сотрудников организаций. В одном документе - куча сотрудников. Т.е., чтобы все записать одним набором записей, надо установить отбор по измерению График - в списке.
Код гораздо читабельнее, а по производительности в транзакции замедлений не замечено.
Вот поэтому и нужен набор записей без отборов с записью в Файл по аналогии с MS SQL MERGE. Возможность удаления по набору записей. Пока это все приходится делать напрямую при больших объемах
кури про основной отбор. На самом деле запись набора может быть записью 100500 наборов.
если основной отбор /детальнее/, чем установленный на набор записей, то происходит запись кучи наборов. Если основной отбор на все измерения - то запись/удаление записи менеджером записи = запись одной записи, Если основной отбор не на все - то запись через менеджер записи = запись набора по основному отбору.
Как в модуле набора записей отличить изменение записи от ее удаления? При изменении записи сначала формируется событие на удаление этой записи (Замещение=истина), потом событие на добавление этой записи (Замещение=ложь). При удалении записи просто формируется событие на удаление записи (Замещение=истина). Никак отличить не могу, поможите дальтонику.
я даже могу прочитать регистр, чтобы посмотреть, есть чего в нем или нет, но в любом случае я не могу понять, это удаление или модификация. ;-( А мне нужно запретить удалять.
Т.к. при модификации сначала вызывается удаление, если его запретить - модификация не пройдет.
Попробуй закончить транзакцию принудительно раньше конца процедуры и посмотреть, что твориться в регистре. ЗЫ. Вроде 1С не поддерживает вложенных транзакций?
Выгрузка в таблицы значений с последующим сравнением не поможет?
Это извращение! Первым идет удаление, а не запись, поэтому что выгружать? Таблица то пустая!
Походу очередная дыра функционала. Можно еще както играться с флажком замещение, но мне кажется ДЫРА.
расскажи, чо хочеш в результате получить - может, кто другой метод предложенить, помимо "игры на замещении".
так я уже рассказал - хочу разрешить редактирование (но только ресурсов, без измерений), но запретить удаление.
Судя из того что есть только право "Изменение" у регистра, ты такое не словишь
гыгыгы. при чем тут права. Речь идет о контроле из модуля.
Не думаю, что дыра - скорее задача не с той стороны решается. С точки зрения системы происходит не модификация, а удаление и создание - а это две большие разницы и отловить можно только внешней оберткой, т.к. система не будет себя нагружать такими подробностями интимной жизни пользователя :)
чем запись отличается от удаления? в том и в другом случае записывается набор
Это мне напоминает ситуацию - захватили немцы деревню, староста бежит и грит - а че, немцы они хорошие, ничего, жить можно. В том то и дело, что невозможность отличить модификацию от удаления ведет к тому, что контроль над изменениями в регистрах сведений нужно как в 77 выносить в форму. А насчет того, что это одно и то же - бросьте. В одном случае это удаление, в другом транзакция из удаления и добавления.
Не прав. Это просто запись в обоих случаях. Просто удаление и модификация - это частный случай записи. База переходит из одного состояния в другое - это основной принцип транзакций, поэтому никак не отследит не перехватывая такие события заранее.
В оперативной памяти компьютера (Какой вопрос, такой ответ). ОФФ: Витя, ты ее сколько лет хранить собираешься? :) /2 И тебе не под силу добавить перед удалением выгрузку в ТЗ?
Да ну? Видишь ли, в теории реляционных СУБД есть оператор SQL UPDATE. 1С почему то использует не UPDATE, а DELETE & INSERT
Читаем про UPDATE и для чего оно применяется: "Важно. Инструкция UPDATE не создает набора результатов. Обновление записей, выполненное с использованием запроса на обновление, нельзя отменить. Чтобы узнать какие записи будут обновлены, выполните запрос на выборку с теми же условиями, и только потом, выполните запрос на обновление. Рекомендуется всегда делать резервные копии данных. Если записи были удалены по ошибке, их можно восстановить из резервных копий. " Т.е. это опять частный случай записи (грубо говоря - с применение отбора, что будем менять)
Если задача отследить действия пользователя - то вполне нормально использовать для этого форму. А потом передавать данные в модуль, например с помощью какой-нибудь экспортной переменной.
мне нужно запретить на программном уровне изменение скажем, реквизита регистра сведений определенным пользователям. Через форму - это вчерашний день, 77, да, там это было нормально.
мдя, как все запущено. видишь ли, если бы 1С передавало в модуль передзаписью, что именно оно пытается сделать. Кстати, а может для РС пощупать при записи. Я вот тут подумал.
Я так полагаю, что система не задумывается о таких мелочах просто делает удаление+запись нового - так быстрее будет.
Об этом должна была не система думать, а проектировщики платформы. Нужен был еще один параметр в процедуре ПередЗаписью (Удаление из модификации / Чистое удаление), на скорости это никак бы не отразилось. Очередная черная функциональная дыра 1С.
Ты не понял - это работает также, как и UPDATE в SQL. Т.е ВСЕ изменения ты должен перехватывать на стадии ДО, а не ВО ВРЕМЯ. Т.е надо убирать не следствие, а причину. Данная функция не предназначена для такой ситуации по причине того, что система не задается вопросом (имхо) изменение каких полей произошло, а просто обновляет запись полностью, что должно быстрее быть, т.к. UPDATE будет работать с отбором. Соответственно - такого флага (модификация или что-нибудь другое) быть не может.
Это было бы справедливо, если бы 1С изменяло через UPDATE, но оно изменяет через DELETE +INSERT, причем не средствами SQL, а из языка.
Работает четко Тонкость: при записи процедура отрабатывается дважды - первый раз удаление (количество = 0), второй раз запись проводок (количество = количество проводок); при отмене проведения - один раз (количество = 0)
говорил уже, в первом вызове я не знаю, удаление это или изменение - число записей по любому-ноль. Если я предположу, что это изменение и буду ждать второго вызова, он может и не произойти - например, если это удаление.
Коряво - но подключай обработчик ожидания на 1-10 сек и смотри, что там произошло за это время. Итого у тебя не так много вариантов решить эту задачу, либо ставить ее по другому :)
В уже почти все написано. Остается в модуль набора добавить переменную-счетчик: первй вызов - удаление, второй - запись новых данных.
Хотя стоп, это идея. ПередЗаписью вызывается дважды. А контроль нужно вносить в ПриЗаписи. Точно, счетчег поможет.
Правда, непонятно, если я в ПриЗаписи напишу Отказ, разорвет ли оно всю транзакцию или только первую запись? Наверное всю!
у тебя будут проблеммы с транкзациями. ведь она может иметь неопределенное кол-во записей, то есть если я в модуле проведения документа в цикле обнавляю 100 элементов регистра, то ты получишь транкзацию (не явную) на 200 шагов. и как ты сможе из большой транкзации вычленить 1 запись. ИХМО - либо будет МЕДЛЕННО либо не получиться.
Нет, ни хрена, все счетчики, которые создаются в модуле набора записей для каждой записи уникальны, т.е. дважды устанавливаются в неопределено. Мдя.
Вообщето при удалении документа вызывается ПриЗаписи где уже свойство ПометкаУдаления = Истина
Когда вызывается призаписи транзакция уже началась Соответсвенно отказ отменяет все
v8: Как отличить запись от удаления? Вот тема. нигде про набор записей
нет это ты не понял. именно это я и хотел до тебя донести, ведь почти всегда модуль регистра выболняеться в БОЛЬШОЙ и ВЫШЕСТОЯЩЕЙ транкзации, и ты не сможешь влиять на конкретную запись. ты сможешь только отменить БОЛЬШУЮ транкзацию.
а отменять ее лучше из того места где она началась например из модуля документа.
Зачем в документы ввели событие ПередЗаписью? ЧТобы не искать по коду, где вызывается запись документа. А ты предлагаешь регресс - назад к 77. Ищем все места, где вызывается запись набора записей и ура. Только это все уже в прошлом, вместе с 77.
По идее можно при удалении не удалять набор записей, а записывать его еще раз, в при записи. ну что то типо этого
Что-то у меня все сильнее крепнет мысль, что Гений не с той стороны задачу решает. Если тебе тупо надо решать вопрос запрета редактирования чего-либо в РС - дык создай свою форму обработки списка/записи и балуйся этим. А Документы.ПередЗаписью никаким образом не относятся к РС.НаборЗаписей.ПередЗаписью - вообще разная тактика работы и назначение
я придумал как тебе сделать. все ГениТальное - ПРОСТО. 1. ЗАПРЕЩАЕШЬ ВСЕМ РОЛЯМ изменять регистр 2. Создаешь модуль с неограничеными правами и в нем описываешь процедуры записи и удаления регистра. далее ЛЮБАЯ обработка обязана пойти через твои обработчики есть 2 минуса 1. придеться переписывать ВСЕ места где происходит запись 2. возможно обойти из другого привелигерованного модуля
Гений опять изобретает сферического коня. Ты когда последний раз заходил в конференцию для партнеров? Почитай посмотри скока там пожеланий/недоработок/багов в платформе. Хоша кто тебя такого красавца туда пустит.. Попроси кого там тему замутить, есть шанс что одинэсники тебе ответят (меня не проси, сижу под паролем двухлетней давности, не хочу светиться)
+ Имелась в виду конференция для разработчиков, ессно
ой, моська ;) исчо кто кого опустит, хотелось бы мне посмотреть ;)
1. Создать глобальную переменную глПризнакЗаписи. 2. Подписать документы на событие ПередЗаписью, и ПриЗаписи 3. В обработчике событий в процедуре ПередЗаписью: глПризнакЗаписи = 0. 4. В обработчике событий в процедуре ПриЗаписи: глПризнакЗаписи = 1. 5. В обработчике событий в процедуре ПриЗаписиРегистровНакопления: условие (глКДО_ПризнакЗаписи = Истина) И (Источник.мТаблицаДвижений = Неопределено) выполнится только для удаления при изменении.
а теперь прочти свой пост ВНИМАТЕЛЬНО . и зацени - почему над тобой стебаются - просто жесть , такой самовлюбленности давно не встречал - типа новый божок.
Ненадежно. К тому же метод работает только для регистров, подчиненных регистратору. Вот то-то и оно, что большинство тупых 1сников просто плескается в своем болотце и не ждет милостей от Селезневки.
У меня все отлично отрабатывает. Думаю достаточно надежно.
я объяснил тебе, что это только для регистраторов. для независимых регистров не катит, а у меня именно такой случай. Кстати, в твоем варианте думаю достаточно анализировать реквизит Проведен документа, а не глобальные флаги.
Конечно, тебе тогда не подходит. Внутри ПриЗаписиРегистровНакопления Проведен всегда истина, как ни странно.
А ты используй версию из базы данных. Регистратор.Ссылка.ПолучитьОБъект
Проверила: Регистратор.Ссылка.ПолучитьОбъект.Проведен тоже всегда ИСТИНА в ПриЗаписиРегистровНакопления.
ты это к чему? А ваще я пока еще на 8.1 не перешел, поэтому подписку на события юзать не могу.
Проверила: Регистратор.Ссылка.ПолучитьОбъект.Модифицированность всегда ЛОЖЬ в ПриЗаписиРегистровНакопления.
это ты кому? Я проверил. Если в модуле набора записей количество записей равно нулю и модифицированность - истина, тогда это удаление, если же модифицированность - ложь, то это изменение. Действительно, отличить удаление от модификации можно. ;-) Спасибо HHHH
А у меня Модифицированность возвращает всегда ЛОЖЬ :(
ты не так смотришь. проверь еще раз. в модуле набора записей в событии перед записью!
Читайте также: