![]() |
![]() |
|
Рассказываю, как работать с кэшем в формах. Дешево и сердито... | ☑ | ||
---|---|---|---|---|
0
Гений 1С
гуру
16.03.08
✎
21:59
|
Короче, запарился я рассчитывать вычисляемые поля для формы списка, да еще и так, чтобы это было быстро...
В общем написал функцию для кэширования. Изучайте други, все просто. В форме, используется функция приоткрытии, показываю также образцы функций-диспетчеров: Процедура ПриОткрытии() ... М=Новый Массив(); М.Добавить("Состояние"); М.Добавить("Категории"); М.Добавить("Внимание"); обСоздатьКэшФормы(ЭтаФорма, "КэшЭлементов", М); ... КонецПроцедуры Функция ДиспетчерВычисленийКэша(П, ИмяКолонки, Ключи) Экспорт Если ИмяКолонки="Категории" Тогда ТЗ=пимПолучитьМассивКатегорийОбъектов(Новый Структура("Дата, Ссылки", ТекущаяДата(), Ключи)); ТЗ.Колонки.Ссылка.Имя="Ключ"; Возврат ТЗ; ИначеЕсли ИмяКолонки="Состояние" Тогда ТЗ=пимПолучитьСостоянияЗадач(Новый Структура("Дата, Ссылки", ТекущаяДата(), Ключи)); ТЗ.Колонки.Ссылка.Имя="Ключ"; Возврат ТЗ; КонецЕсли; КонецФункции Функция ДиспетчерВыводаКэша(П, ОформлениеСтроки, СтрокаКэша, ИмяКолонки=Неопределено) Экспорт Если ИмяКолонки="Категории" Тогда ОформлениеСтроки.Ячейки.Категории.УстановитьТекст(СтрокаКэша.Категории); ИначеЕсли ИмяКолонки="Состояние" Тогда Картинка=пимКартинкаСостоянияЗадачи(СтрокаКэша.Состояние); Если Картинка<>Неопределено Тогда ОформлениеСтроки.Ячейки.Состояние.УстановитьКартинку(Картинка); КонецЕсли; КонецЕсли; КонецФункции Процедура СправочникСписокПриПолученииДанных(Элемент, ОформленияСтрок) //Элементы=Новый Массив(); //ЭлементыКатегории=Новый Массив(); //ЭлементыАктуальность=Новый Массив(); //Отрисовываем то, что в кэше... обОтрисоватьКэш(Новый Структура("Форма, ОформленияСтрок, Элемент, ДиспетчерВычислений, ДиспетчерВывода, КолонкаКлюча", ЭтаФорма, ОформленияСтрок, ЭлементыФормы.СправочникСписок, "ДиспетчерВычисленийКэша", "ДиспетчерВыводаКэша", "Ссылка")); КонецПроцедуры Модуль с используемыми функциями: //ПОДБИБЛИОТЕКА: КЭШ ФОРМЫ //20071115 fixin //Создает кэш в форме для кэширования данных табличной части Функция обСоздатьКэшФормы(Форма, ИмяКэша, Колонки=Неопределено)Экспорт КэшЭлемент=Форма.ЭлементыФормы.Добавить(Тип("ПолеВвода"),"_c4dc2eda1dcc454b94b013f8fdb951b9"+ИмяКэша, ложь); ТЗ=Новый ТаблицаЗНачений(); ТЗ.Колонки.Добавить("Ключ"); Если Колонки<>Неопределено Тогда Для Каждого Колонка Из Колонки Цикл ТЗ.Колонки.Добавить(Колонка); КонецЦикла; КонецЕсли; Структура=Новый Структура(); Структура.Вставить("Данные", ТЗ); Структура.Вставить("Колонки", обСкопироватьМассив(Колонки)); КэшЭлемент.СписокВыбора.Очистить(); КэшЭлемент.СписокВыбора.Добавить(Структура); КонецФункции //20071115 fixin Функция обВернутьКэшФормы(Форма, ИмяКэша) Экспорт Возврат Форма.ЭлементыФормы["_c4dc2eda1dcc454b94b013f8fdb951b9"+ИмяКэша].СписокВыбора[0].Значение; КонецФункции //20071115 fixin Функция обОчиститьКэш(Кэш) Экспорт Кэш.Данные.Очистить(); //Очищает таблицу значений КонецФункции //20071115 fixin //Ищет значение в кэше, если Создавать=истина, то если не находит, добавляет //Возврат - Неопределено или строку кэша. Функция обНайтиВКэше(Кэш, Значение, Создавать=ложь) Экспорт Стр=Кэш.Данные.Найти(Значение, "Ключ"); Если Стр=Неопределено Тогда Если Создавать Тогда Возврат обЗанестиВКэш(Кэш, Значение); КонецЕсли; Возврат Неопределено; КонецЕсли; Возврат Стр; КонецФункции //20071115 fixin //Удаляет запись из кэша Функция обУдалитьИзКэша(Кэш, Значение) Экспорт СтрКэша=обНайтиВКэше(Кэш, Значение); Если СтрКэша<>Неопределено Тогда Кэш.Данные.Удалить(СтрКэша); КонецЕсли; КонецФункции //20071115 fixin //Не проверяет наличие в кэше, просто добавляет запись в кэш!!! Функция обЗанестиВКэш(Кэш, Значение) Экспорт Стр=Кэш.Данные.Добавить(); Стр.Ключ=Значение; Возврат Стр; КонецФункции //Параметры // Форма - форма // ОформлениеСтрок - оформление строк // Элемент - элемент списка // КолонкаКлюча - ключевое поле. // ДиспетчерВычислений - имя функции по вычислению данных // ДиспетчерВывода - имя функции по выводу данных Функция обОтрисоватьКэш(П) Экспорт Перем Кэш; Перем Форма, ОформленияСтрок, Элемент, КолонкаКлюча, ДиспетчерВычислений, ДиспетчерВывода; П.Свойство("Форма", Форма); П.Свойство("ОформленияСтрок", ОформленияСтрок); П.Свойство("Элемент", Элемент); П.Свойство("КолонкаКлюча", КолонкаКлюча); П.Свойство("ДиспетчерВычислений", ДиспетчерВычислений); П.Свойство("ДиспетчерВывода", ДиспетчерВывода); Кэш=обВернутьКэшФормы(Форма, "КэшЭлементов"); ВидимыеКолонки=Новый Массив(); //Сначала смотрим, видимы ли колонки Для Каждого Эл ИЗ Кэш.Колонки Цикл Если Элемент.Колонки.Найти(Эл)=Неопределено Тогда Продолжить; КонецЕсли; ВидимыеКолонки.Добавить(Эл); КонецЦикла; //Оптимизация - если колонок кэша нет в списке, то пропускаем Если ВидимыеКолонки.Количество()=0 Тогда Возврат истина; КонецЕсли; //Нам нужно найти ссылки, для которых не найдено значение кэша ВычисляемыеСтроки=Новый Структура(); ВычисляемыеКлючи=Новый Структура(); Для Каждого Колонка из ВидимыеКолонки Цикл ВычисляемыеСтроки.Вставить(Колонка, Новый Массив()); ВычисляемыеКлючи.Вставить(Колонка, Новый Массив()); КонецЦикла; ЛокальныйКэш=Новый ТаблицаЗначений(); ЛокальныйКэш.Колонки.Добавить("Ключ"); ЛокальныйКэш.Колонки.Добавить("ОформлениеСтроки"); ЛокальныйКэш.Колонки.Добавить("СтрокаКэша"); //Смотрим, каких данных не хватает в кэше... Для Каждого ОформлениеСтроки ИЗ ОформленияСтрок Цикл ТекСтр=ОформлениеСтроки.ДанныеСтроки; //Строка оформления Ключ=ТекСтр[КолонкаКлюча]; СтрокаКэша=обНайтиВКэше(Кэш, Ключ, истина); //Строка кэша СтрЛок=ЛокальныйКэш.Добавить(); СтрЛок.Ключ=Ключ; СтрЛок.ОформлениеСтроки=ОформлениеСтроки; СтрЛок.СтрокаКэша=СтрокаКэша; Для Каждого Колонка из ВидимыеКолонки Цикл Ключ=ТекСтр[КолонкаКлюча]; Если СтрокаКэша[Колонка]=Неопределено Тогда ВычисляемыеКлючи[Колонка].Добавить(Ключ); ВычисляемыеСтроки[Колонка].Добавить(СтрЛок); КонецЕсли; КонецЦикла; КонецЦикла; //Можно усовершенствовать - если есть невидимая колонка и она вдруг расчитывается //То ее тоже можно заносить в кэш, т.е. идти в том числе и по невидимым колонкам. //Вызываем диспетчера для вычисления значения колонки //Вычисляем значения колонки - в виде таблицы значений Ключ - Колонка1, Колонка2 Для Каждого ИмяКолонкиВыч Из ВидимыеКолонки Цикл //Если все данные есть в кэше, ничего не делаем Если ВычисляемыеКлючи[ИмяКолонкиВыч].Количество()=0 Тогда Продолжить; КонецЕсли; //Вычисляем значения, которых не хватает ТЗ=Вычислить("Форма."+ДиспетчерВычислений+"(П, ИмяКолонкиВыч, ВычисляемыеКлючи[ИмяКолонкиВыч])"); Если ТЗ=Неопределено Тогда ТЗ=Новый ТаблицаЗначений(); ТЗ.Колонки.Добавить("Ключ"); ТЗ.Колонки.Добавить(ИмяКолонкиВыч); КонецЕсли; ТЗ.Колонки.Добавить("СтрокаКэша"); //Помечаем что колонки уже не нужны Для Каждого КолонкаТЗ ИЗ ТЗ.Колонки Цикл ИмяКолонки=КолонкаТЗ.Имя; Если НЕ ВычисляемыеСтроки.Свойство(ИмяКолонки) Тогда Продолжить; КонецЕсли; //Проставляем значения из ТЗ Для Каждого СтрТЗ ИЗ ТЗ Цикл СтрЛок=ЛокальныйКэш.Найти(СтрТЗ.Ключ, "Ключ"); //Условие по идее никогда не должно сработать, но мало ли СтрЛок.СтрокаКэша[ИмяКолонки]=СтрТЗ[ИмяКолонки]; КонецЦикла; //Если в ТЗ указаны значения не для всех ключей Если ТЗ.Количество()<ВычисляемыеКлючи[ИмяКолонки].Количество() Тогда Для Каждого СтрЛок ИЗ ЛокальныйКэш Цикл Если СтрЛок.СтрокаКэша[ИмяКолонки]=Неопределено Тогда СтрЛок.СтрокаКэша[ИмяКолонки]=NULL; КонецЕсли; КонецЦикла; КонецЕсли; ВычисляемыеКлючи[ИмяКолонки].Очистить(); КонецЦикла; КонецЦикла; //Теперь можем смело выводить все, что надо... Для Каждого СтрЛок ИЗ ЛокальныйКэш Цикл Для Каждого ИмяКолонки ИЗ ВидимыеКолонки Цикл Выполнить("Форма."+ДиспетчерВывода+"(П, СтрЛок.ОформлениеСтроки, СтрЛок.СтрокаКэша, ИмяКолонки)"); КонецЦикла; Выполнить("Форма."+ДиспетчерВывода+"(П, СтрЛок.ОформлениеСтроки, СтрЛок.СтрокаКэша, Неопределено)"); КонецЦикла; КонецФункции |
|||
1
ТелепатБот
гуру
16.03.08
✎
21:59
|
Книга знаний: Доступ к глобальным переменным, процедурам и функциям из общих модулей
Книга знаний: Тип реквизита и тип значения Книга знаний: Проверка типов Книга знаний: Размещение колонки с остатками в списке справочника Книга знаний: Быстрое создание и настройка правил обмена для зависимых объектов в Конвертации Данных v8 |
|||
2
Гений 1С
гуру
16.03.08
✎
22:01
|
(1) телепат, ты угадал: Книга знаний: v8: Размещение колонки с остатками в списке справочника
но я хотел сделать так, чтобы быстро разрабатывать код... |
|||
3
Asmody
модератор
17.03.08
✎
00:03
|
(0) блин, ты б построитель запроса наконец изучил бы толком и не изобретал очередное квадратное колесо
|
|||
4
Злопчинский
17.03.08
✎
02:00
|
блин.. понятно, что здорово, но - здорово непонятно...
|
|||
5
Kraft
17.03.08
✎
07:24
|
генетально...
|
|||
6
MaxS
17.03.08
✎
08:35
|
(0) в типовых для этого используют не таблицу значений, а соответствие.
|
|||
7
Гений 1С
гуру
17.03.08
✎
09:23
|
(3) Асмоди, проясни свою светлую мысль.
(6) Не гони товарищ, там не сделано это таким образом, чтобы работа с кэшем занимала пару строчек, как у меня. Я унифицировал сей механизм... Если хочешь поспорить, давай код в студию. А потом прикинь, сколько кода нужно еще написать, чтобы добавить еще одну вычислимую колонку. А у меня независимо от числа добавляемых колонок код простой - всего лишь меняются функции диспетчеров и все... |
|||
8
Господин ПЖ
17.03.08
✎
09:46
|
А в 8.1 кеш работает? В списке при выводе строк весь список через "ОформлениеСтроки" не обрабатывается - только то что выводится на экран + еще пара строк... Если промотать список дальше - то что было выведено было раньше через "ОформлениеСтроки" теряется безвозвратно. Т.о. получается ситуация - данные в кеше есть, а списке на форме - нет. Есть ли смысл в таких кэшах?
|
|||
9
Defender aka LINN
17.03.08
✎
09:51
|
Мда... Весенне обострение.
Ждите новых и новых разновидностей велосипедов. |
|||
10
Гений 1С
гуру
17.03.08
✎
09:51
|
(8) Есть конечно же есть... Выигрыш в производительности вывода на экран.
Можно очищать кэш скажем или каждые 30 секунд или после наполнения его до какого-то уровня, например на 10 000 позиций. ;-) Кстати, в управляемом приложении источником для формы может быть компоновка данных (т.е. сложный запрос). Там кэш будет не нужен... Я обычно делаю при закрытии формы или изменении данных рассылку широковещательных сообщений открытым формам, при получении которых кэш очищается, то бишь информация становится актуальной. В любом случае юзверю приятнее нажать обновить, чем ЖДАТЬ. |
|||
11
Господин ПЖ
17.03.08
✎
10:03
|
(10) >>Есть конечно же есть... Выигрыш в производительности вывода на экран.
Речь не о производительности. Речь о том что при неполном чтении списка и уничтожении в дальнейшем в нем уже прочитанного "смысла" в кэшах нет. |
|||
12
Гений 1С
гуру
17.03.08
✎
10:12
|
(11) не уловил твою мысль. Что значит нет?
а если ты вверх-вниз проскроллируешь, т.е. вернешься к тем данным, что уже были показаны? |
|||
13
Господин ПЖ
17.03.08
✎
10:15
|
(12) ты к ним уже можешь и не вернуться - они "затерты" новыми.
|
|||
14
Гений 1С
гуру
17.03.08
✎
10:18
|
(13) блин, что значит могу не вернуться:
АБВГДЕЖЗИЙКЛМНО Допустим на экран выводится по 4 элемента АБВГ - кэш АБВГ нажимаю пждн: ДЕЖЗ - кэш АБВГДЕЖЗ нажимаю пждн: ИЙКЛ - кэш АБВГДЕЖЗИЙКЛ нажимаю пжап: ДЕЖЗ - кэш АБВГДЕЖЗИЙКЛ (используется) |
|||
15
MaxS
17.03.08
✎
10:45
|
(7) КонсольЗаданий.epf
ФормаКонсоли, переменная ФоновыеЗаданияСоответствие используется в качестве кэша... а вообще, по моему необходимость в subj должна возникать достаточно редко. Если это не так, значит база данных неоптимальная, т.к. приходится постоянно что-то расчитывать, вместо того, чтобы просто взять из регистров... ;) да и некогда мне спорить. я лучше поработаю ;) |
|||
16
КонецЕсли
17.03.08
✎
11:05
|
(14) Он имеет в виду, что данные могут быть изменены другим пользователем, а тебе тебе будет отображаться устаревщее состояние - из твоего кеша.
|
|||
17
Гений 1С
гуру
17.03.08
✎
11:38
|
(16) Я же говорю - через рассылку широковещательных сообщений обновляю кэш.
(15) Неоптимальная гришь? и тут же пишешь что данные в регистрах хранятся. ;-) Так вот, 1с позволяет выводить в форму только реквизиты объекта, остальное надо рассчитывать. И на файловой версии эти рассчеты тормозят по-любому. |
|||
18
MaxS
17.03.08
✎
11:53
|
(17) в регистрах должно лежать всё посчитанное, а форма должна просто отображать результат.
Зачем каждому пользователю тыщю раз просчитывать(брать из кэша) одно и то же в форме? Если эти данные можно посчитать один раз при проведении документа. |
|||
19
Гений 1С
гуру
17.03.08
✎
12:03
|
(18) В твоих словах есть резон... ;-)
Однако можно такую хрень, как у мя использовать для того, чтобы вытаскивать данные в том числе и из регистров, учитывая какие колонки видимые. Суть проджекта была в упрощении разработки таких форм - их у меня вагон и тележка.. ;-) |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |