gifts2017

"Справочник плюс". Прямая запись в справочники 1С 7.7

Опубликовал Андрей Портянко (an_2) в раздел Программирование - Практика программирования

"Справочник плюс" - замена штатного объекта "Справочник.ХХХ"
Предназначен для "прямой" записи, и дает возможность управлять табличными подсказками при чтении.
Позволяет избавиться от монопольных блокировок таблиц справочников и таблицы констант.
Главным мотивом написания было избавиться от вылетов 1С из-за deadlock-ов и "недопустимых состояний курсоров".
Состоит из нескольких классов 1с++, нескольких переменных и методов в глобальном модуле.

  Изменения от 12.06.2012:

Изменено именование классов со "Справочник.ХХХ.А" / "Справочник.ХХХ.Б" на: "Справочник.ХХХ",

поэтому теперь при подключении классов нет необходимости переименовывать все справочники в конфигурации.


Немалая часть вылетов 1С 7.7 на SQL базах связано с записью в справочники. Иногда 1с про ошибки говорит и вылетает. Это desdlock-и и "недопустимые состояния курсора". А иногда уходит по английски, ничего не сказав. Я думаю это связано с очень поверхностной обработкой ошибок которые 1С получает от SQL.

Что "Справочник плюс" дает.

1. Запись выполняется без монопольных блокировок таблиц.

2. Можно управлять блокировками используя "почти штатные" методы.

3. Скорость записи немного выше.

4. Открытая форма элемента не блокирует запись.

5. Пишется только то, что изменил пользователь. Например пользователь мог открыть форму элемента, поменять там один реквизит, пойти покурить. Пока форма открыта, программно было записано 2 реквизита. Когда пользователь нажмет ОК. Запишется только один, изменненый им, реквизит.

6. Следствие пункта 5: Легко отслеживать и, при необходимости, фиксировать, что менял пользователь.

7. Нет нужды в перехвате событий справочника как объекта. Все события у вас уже под руками.

8. Со временем хочу заменить все штатные (курсорные) выборки на запросы. И скорость выше и нагрузка не систему ниже и встреч с "недопустимыми состояниями курсора" не будет.


Как это работает:

Как подключаются компоненты и классы можно посмотреть в тестовой конфигурации и, если чего не понятно, почитать на www.1cpp.ru/

Я укажу только суть:

1. В глобальнике:

Еще до загрузки 1CPP.dll проверяется и при необходимости пересоздается файл определения классов с полным перечнем справочников.

Далее при загрузке 1CPP.dll создаются классы вида "Справочник.ХХХ", которые являются наследниками от "Reference.ХХХ" и "ТаблицаЗначений".

2. В формах:

События формы перехватываются Классом ПерехватчикГК (Это класс выполняющий роль фабрики событий группового контекста) и направляются в класс ПерехватчикГК.Справочник - класс обслуживающий прямую запись во всех формах справочников (и в формах списков и  элементов и групп). В классе можно указать "Неперехватываемые" справочники.

При выполнении события ПриЗаписи() устанавливается СтатусВозврата(0) 1с-у говорим, что записывать не будем, создаем объект "Справочник.Вид.Б" и при специальным методом "ЗаписатьИзФормы" пишем самостоятельно.

Минусы при записи из формы:

1. После записи нового элемента форма не знает, что элемент записан, поэтому Выбран() = 0 а ТекущийЭлемент() = пустое значение. Для обхода этой проблемы к контексту формы добавляется свойство: ТекущийЭлементПрямойЗаписи. А для получения текущего элемента формы лучше использовать глобальную функцию: глТекущийЭлементФормы(Контекст).

 

ТРЕБОВАНИЯ и ОГРАНИЧЕНИЯ:

1. FormEx.dll, 1CPP.dll (вложены)

2. УРБД не поддержано. Если разработка заинтересовала готов поддержать.

3. В ПриЗаписи() нельзя использовать метод формы Записать() - происходит выход 1с-а в астрал.

4. Если используется событие ФормаПослеЗаписи() в начале Метода НЕОБХОДИМО вставить: СтатусВозврата(1); это связано с особенностью реализации этого метода: при СтатусеВозврата() = 0 в ПриЗаписи() этот метод уже на входе имеет СтатусВозврата() = 0

5. ТекущийЭлемент() в форме необходимо получать через глобальную функцию

глТекущийЭлементФормы(Контекст)

6. Если запись выполняется без закрытия формы, то После записи форма закрывается, а затем открывается. Так проще.

7. Наверно нужно причислить к недостаткам: Фабрика событий не стандартный класс фабрики событий 1Cpp. Ну не нравится мне передача параметров через список. Сначала укладываем, потом разукладываем это ведь время.


Состав архива:

 Каталог тестовой базы со всем необходимым внутри + Выгрузка этой же базы.

 

Пример использования:

Как генерить гарантированно уникальные записи в справочиках. 

Измененный метод  НайтиПоРеквизиту() имеет два дополнительных параметра. Синтаксис:

НайтиПоРеквизиту(ИмяРеквизита,Значение,ФлагГлобальногоПоиска=1,Хинт=0,ТолькоСсылку=0)

Хинт - способ чтения. Можно указать строкой, можно числом. Строка - все, что съест ms SQL; Число: наиболее полезные подсказки: 0 - nolock, 1 - readcommitted, 2 - serializable, 3 - updlock

ТолькоСсылку значения: 0 - прочитать все реквизиты (по умолчанию); 1 - только найти ссылку (ТекущийЭлемент())  

спр = СоздатьОбъект("Справочник.УникальныйПоРеквизиту");
// Ищем ссылку с хинтом 2 (serializable) (гарантированно записанные и никем не изменяемые в момент чтения данные)
Если спр.НайтиПоРеквизиту("УникальныйРеквизит",125,1,2,1) = 0 Тогда
    // Если Не нашли: открываем транзакцию и читаем с хинтом 3 (updlock) - чтение, дающее гарантию, что до завершения
    // транзакции никто другой не сможет записать анналогичные данные. (Данные соответсвующие нашим условиям).
    НачатьТранзакцию();
    Если спр.НайтиПоРеквизиту("УникальныйРеквизит",125,1,3,1) = 0 Тогда
        // Если не нашли со спокойной совестью пишем гарантия уникальности = 100%
        спр.Новый();
        спр.УникальныйРеквизит= 125;
        спр.Записать();
    КонецЕсли;
    ЗафиксироватьТранзакцию();
КонецЕсли;  


Скачать файлы

Наименование Файл Версия Размер
SpravochnikPlus.rar 19
.rar 1,12Mb
12.06.12
19
.rar 1,12Mb Скачать

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Епрст (Ёпрст) 28.05.12 13:36
Это, а как же методы НовыйКод,НовыйИД класса SQLLOck ?
2. Епрст (Ёпрст) 28.05.12 13:39
>>>>Пробовал переопределить СоздатьОбъект("Справочник.Вид"); без всяких .А/.Б - ничего хорошего не получилось.

А в чем именно был затык ?
На каких именно методах ?
Что не удалось переопределить своим классом ?
3. hodok (an_2) 28.05.12 14:29
(1) Ёпрст,
>> Это, а как же методы НовыйКод,НовыйИД класса SQLLOck ?
Сначала пришлось отказаться от НовыйКод
На одном справочнике SQLLOck был не в состоянии правильно генерить новый уникальный код. Что именно происходило не так я к сожалению сказать не могу. Вникать не стал. Могу только сказать про сам справочник. Там был текстовый код длиной 5 символов и параллельно использовалось несколько разных префиксов длиной в 1 символ.
Не стал вникать еще и потому, что было 2 дополнительных мотива:
1. Проверку уникальности новых кодов с учетом всех нюансов я уже сделал до этого. То есть до самостоятельной генерации оставалось совсем малость.
2. Самостоятельно генерить было удобнее. Более управляемый процесс. Сейчас при генерации я анализирую новый код и, если он неудачный меняю правила и генерю по-другому, либо, если вариантов, нет - выбрасываю исключение.

Теперь по поводу НовыйИД
Опять таки сначала юзал SQLLOck. После анализируя замеры производительности, увидел, что SQLLOck потребляет слишком много времени. Посмотрел сколько необходимо времени на получение MAX(ID) и отказался от SQLLOck полностью.
4. hodok (an_2) 28.05.12 15:07
(2) Ёпрст,
>>>>Пробовал переопределить СоздатьОбъект("Справочник.Вид"); без всяких .А/.Б - ничего хорошего не получилось.

>>А в чем именно был затык ?
>>На каких именно методах ?
>>Что не удалось переопределить своим классом ?

Мгновенный вылет 1с при попытке создания Объекта.
Использую 25 релиз.
Наследовать пытался, как рекомендовали на форуме от "Reference".

Я подумал, что какие бы ни были причины лучше не собирать лишние грабли. Тем более что как я понял ответ на вопрос что делать с ТипЗначенияСтр() так и остался открытым.
У меня предприятия большие и самый важный показатель работы системы - стабильность. Собственно и класс для этого рисовался.
Плюс ветка посвященная этому вопросу была довольно стара и закончилась ничем:
http://www.1cpp.ru/forum/YaBB.pl?num=1175586636/0
В общем как-то так.
5. hodok (an_2) 28.05.12 15:18
(2) Ёпрст,
Да и я, если честно, решил что наследование без изменения имени это что-то из разряда "фича, которую лучше обходить стороной". На форуме не мало было сообщений о нестабильности 1с-а при таком наследовании.
6. hodok (an_2) 28.05.12 15:45
(2) Ёпрст,
Да. Забыл написать свое мнение по этому поводу.
Я очень даже за отказаться от .А/.Б
Если есть желание разобраться в причинах вылетов и устранить проблемму. Я готов к сотрудничеству.
Может проблемма где-то у меня.
Пойду покопаю :)
7. Епрст (Ёпрст) 28.05.12 15:56
Для каких-то нужд тоже подменял документ своим классом, потом забил на это дело.
Надо скачать посмотреть твой .
Просто у меня уже используется перехватчик для своих классов.
Грузить еще один - пересматривать весь код :)
8. hodok (an_2) 28.05.12 16:04
(7) Ёпрст,
Я парень не религиозный.
Если отряд идет не в ногу я один в ногу, то надо думать что что-то со мой не так.
Я к тому, что следует мне переписать перехватчик. Точнее наверно лучше заюзать общепринятый.
Вопрос только в том какой он общепринятый?
Тот, который в классе "УправлениеФормой"?
На форуме я находил разные классы.
Особенно меня поразил своей мудреностью тот которые в "Репозитарий классов 1С++ в единой конфе".
9. hodok (an_2) 28.05.12 16:21
Только что посмотрел "УправлениеФормой.ert"
Там на мой взгляд есть одна проблемма:

Процедура Событие_ОбработкаВыбораЗначения(ВыбЗнач,ИДАтрибута,ФСО) Экспорт
СЗПараметры = СоздатьОбъект("СписокЗначений");
СЗПараметры.Установить("ВыбЗнач",ВыбЗнач);
СЗПараметры.Установить("ИДАтрибута",ИДАтрибута);
СЗПараметры.Установить("ФСО",ФСО);
СообщитьПодписчикам("ОбработкаВыбораЗначения",СЗПараметры);
ФСО = СЗПараметры.Получить("ФСО");
Перехватчик.ВыполнитьОригинальноеСобытиеГК(КонтекстФормы,"ОбработкаВыбораЗначения",ВыбЗнач,ИДАтрибута,ФСО);
КонецПроцедуры

Я наблюдал ситуации, когда Метод "ОбработкаВыбораЗначения" подписчиков "Съедает" события.
Явление редкое но бывает. Закономерностей сказать не могу.
Лечил тем, что переименовівал на: "Событие_ОбработкаВыбораЗначения"
10. hodok (an_2) 28.05.12 17:50
(9) hodok,
> Под "Метод "ОбработкаВыбораЗначения" подписчиков "Съедает" события" я имел ввиду следующее: Событие вызывается в первый и единственный раз в модуле какого нибудь подписчика и до перехватчика событие не доходит.
11. it.net (avhrst) 29.05.12 00:40
Даеш нормальную обработку транзакций :)
12. Епрст (Ёпрст) 29.05.12 09:20
Тот что в УправленииФормой был изначально не верным - в нём было слишком много мысора - пустых объявлений методов.
Каков он сейчас - не знаю, не ведаю, не использую.
У меня свой
:)
13. Андрей Портянко (an_2) 31.05.12 05:22
(2) Ёпрст,(6) hodok,
Накопал. Проблемму нашел и исправил. Скоро залью исправленный архив.
При желании можно будет переопределять объект "Справочник.Вид" без А/Б.
Поскольку вероятность Использования метода к ТипЗначенияСтр() к созданному объекту "Справочник.Вид" почти = 0.
В принципе рабочий вариант.
Но ТипЗначенияСтр() надо будет иметь ввиду при использовании.
14. IR IR (Artemuch2) 06.07.12 15:39
>> Это, а как же методы НовыйКод,НовыйИД класса SQLLOck ?
Сначала пришлось отказаться от НовыйКод
На одном справочнике SQLLOck был не в состоянии правильно генерить новый уникальный код. Что именно происходило не так я к сожалению сказать не могу. Вникать не стал. Могу только сказать про сам справочник. Там был текстовый код длиной 5 символов и параллельно использовалось несколько разных префиксов длиной в 1 символ.
Не стал вникать еще и потому, что было 2 дополнительных мотива:
1. Проверку уникальности новых кодов с учетом всех нюансов я уже сделал до этого. То есть до самостоятельной генерации оставалось совсем малость.
2. Самостоятельно генерить было удобнее. Более управляемый процесс. Сейчас при генерации я анализирую новый код и, если он неудачный меняю правила и генерю по-другому, либо, если вариантов, нет - выбрасываю исключение.

Теперь по поводу НовыйИД
Опять таки сначала юзал SQLLOck. После анализируя замеры производительности, увидел, что SQLLOck потребляет слишком много времени. Посмотрел сколько необходимо времени на получение MAX(ID) и отказался от SQLLOck полностью
15. Андрей Портянко (an_2) 06.07.12 15:58
(14) Artemuch2,
????
Я так понимаю очепятка?