29.03.2013, 12:13 | #1 |
Участник
|
Доброго времени суток комрады.
Столкнулся вот недавно с задачкой на первый взгляд простой, но как оказалось на деле, не всё так просто, как кажется на первый взгляд. Итак, есть у нас таблица и столько в ней полей на создавали, что всё уже финита, больше нельзя. Нельзя, но нужно. Что мы для этого делаем? Конечно же создаём ещё одну таблицу, создаём в ней такой же первичный ключ как и в первой и пытаемся как-то связать эти 2 таблицы. Вторя таблица открывается на собственной форме. Если Вы делали это и знаете как решается данная проблема, дальше можете не читать, а просто подсказать решение, если нет, велком в рассуждения ниже. Вот тут то и начинаются интересности. Ну ладно, для начала мы просто создаём во второй таблицы все записи, которые есть в первой, процедура долгая (если первая таблица большая), но разовая, не страшно. А вот теперь вопрос: как сделать так, что бы при добавлении записей в первую таблицу, они добавлялись и во вторую? Казалось бы, есть замечательный триггер OnInsert. Был бы замечательным, если бы Нав не считал, что его можно не запускать при вставке новой записи в таблицу. Да, первая таблица, это всем известная Sales Invoice Header, и при учёте продажи, триггер OnInsert у неё не запускается. Можно конечно полазить по коду и везде по вставлять TRUE в вызов INSERT, но этот подход мне не нравится по ряду вполне очевидных причин. Был бы доступ к SQL, можно было бы простенький запрос на ваять, который вычитал бы из первой таблицы вторую и полученный результат можно было бы использовать на OnOpenForm для добавления записей во вторую таблицу, но доступа к SQL нет. А Нав, насколько мне известно, таких операций делать не умеет, по крайней мере за вменяемое время. Следующая мысль (у меня она была на самом деле первой), это создавать записи во второй таблице, по мере обращения к ней. Т.е. на формочке мы открываем первую таблицу и на OnAfterGetRecord проверяем, есть ли у нас соответствующая запись во второй таблице? Если нету, то создаём её. И тут мы сталкиваемся с очередной проблемой. Мы не можем в этом триггере написать: Table2.INSERT; получим ошибку: "Внесение изменений в базу данных до начала выполнения транзакции невозможно". Обошёл я это ограничение довольно хитро. И так, на форме у нас Table1, а к ней создаём субформу с Table2. Субформа создаёт записи в Table2 без проблем, если что-нить в ней ввести. И так, прячем куда-нибудь субформу, но только не делаем visble := false, иначе она перестанет работать (такая вот у Нава логика ) и пишем на субформе функции, которые будут просто инициализировать запись в Table2 и функции, которые будут записывать в неё значения. Отображаем то мы всё в одном TableBox, т.е. и Table1 и Table2 у нас отображаюсят в одном TableBox. Table1 отображается в нём на прямую, а Table2 через переменную. И всё бы хорошо, если бы не флоуфилды. Да, в Table2 у нас есть парочка флоуфилдов. К чему это ведёт? Записи которых проинициализированы в Table2, с ними всё в порядке, а вот которые ещё не проинициализированы, в них отображается последнее что бы вычислено в данном поле. Что в общем-то беда. В данный момент я склоняюсь к тому, что бы отказаться от флоуфилдов, несмотря на то, что значения в них нужно обновлять. Т.е. на OnAfterGetRecord, мы будем каждый раз вычислять значение и записывать его в Table2, если оно изменилось. Знаю что намудрил, но это от безысходности. Потому и пишу, что может кто-то уже сталкивался с такой проблемой или может окинет её свежим взглядом, да скажет: "Да там же всё просто, сделай вот так и будет тебе счастье" Ещё раз уточню постановку задачи. Нужно в одной табличной форме отображать данные с двух связанных таблиц и при этом следить, что бы во второй таблице были все записи из первой. |
|
|
За это сообщение автора поблагодарили: mira (1). |
29.03.2013, 13:59 | #2 |
Участник
|
Мне кажется нужно разделить задачи отображения и синхронизации таблиц.
И на тригере insert не зацикливаться, а где нужно при учете вставлять записи во вторую таблицу. |
|
29.03.2013, 14:36 | #3 |
Участник
|
Вот это вот "где нужно", мне и не нравится. Во-первых таких мест может быть довольно много и не все они могут быть очевидны, а во вторых, теоретически могут появляться и новые места "где нужно".
|
|
29.03.2013, 15:45 | #4 |
MCTS
|
Цитата:
Приветствую, С формами игрался - не понравилось. Версия клиента какая? В 2009 есть глобальные триггеры в первом Ку на модификацию данных. Синхронизация с СРМ на них сделана. Я бы туда смотрел. |
|
29.03.2013, 17:31 | #5 |
Участник
|
Цитата:
Сообщение от apanko
Цитата:
Приветствую, С формами игрался - не понравилось. Версия клиента какая? В 2009 есть глобальные триггеры в первом Ку на модификацию данных. Синхронизация с СРМ на них сделана. Я бы туда смотрел. Точняк же! Я ведь и сам делал синхронизацию данных между фирмами с помощью этих триггеров. Вот это я и имел ввиду, когда писал "окинет свежим взглядом". А то, когда в проблему зарываешься, обычно не видишь ничего дальше своего носа Спасибо! |
|
01.04.2013, 10:50 | #6 |
Участник
|
А я бы снес с таблицы несколько полей по 250 символов (вынес бы куда-нибудь нафиг). Больше не знаю чем еще можно
Однако прошу прощения, если ошибаюсь |
|
01.04.2013, 12:01 | #7 |
Участник
|
Цитата:
По мне надо идти по пути рефакторинга таблицы. Делать сложные решения по обходу технического ограничения NAV в 4к - гораздо хуже в дальнейшей поддержке. |
|
03.04.2013, 14:58 | #8 |
Участник
|
Оно то верно что путь рефакторинга - самый верный путь, как верно и то, что на него (на рефакторинг) почти никогда нет ни времени, ни ресурсов. Ну не объяснишь ты людям зачем тратить время, а соответственно и деньги на то, что и так работает.
|
|
04.04.2013, 08:37 | #9 |
Участник
|
Можно попробовать нарисовать кривую стоимости поддержки с одной табличкой и двумя . Ну а рялом - стоиомть разового рефакторинга. Может подействует.
Если уже совсем прижало, методы для работы с обеими таблицами нужно однозначно собирает в одном месте (лучше в 1 таблице) - Find2, GET2, Next2, MODIFY2, DELETE2, INSERT2, в этим методах собственно соберется функционал синхронизации. Ну и по всему коду конечно массовая замена FIND, GET, NEXT, MODIFY, DELETE, INSERT на новые функции. |
|