AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: База знаний и проекты
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 10.02.2003, 09:22   #1  
Андре is offline
Андре
Moderator
Сотрудники компании GMCS
 
2,375 / 464 (20) +++++++
Регистрация: 03.12.2001
Вставка строк в таблицы Аксапты сторонними средствами
У меня при работе сАксаптой периодически возникает необходимость/желание вставлять данные в таблицы Аксапты какими-либо сторонними средствами. Это может быть как и внешняя программи, так и хранимая процедура на сервере или DTS. Основная проблема при данном подходе – это RecID. Целое число, уникальное в пределей все базы данных, которое генерит Аксапта для каждой вставляемой строки.

Так как по полям DataArea+RecId Аксапта создает уникальный индекс, оставлять это поле незаполненным невозможно. Значит нужно выработать механизм, который позволит внешним программа правильно генерировать это RecId.

За генерацию RecID в Аксапте отвечают таблица SystemSequences и класс systemSequence. Про структуру и назначение отдельных столбцов таблицы на форуме уже рассказывали – поэтому не буду повторяться. А вот класс, а точнее его методы рассмотрим:


public final int nextVal( [tableId _tableId = 0] ) – возвращает следующий RecID. Это не обязательно тот RecID, который хранится в таблице SystemSequences. Дело в том, что Аксапта выделяет RecId партиями и значение в таблице указывает на первый RecId следющей партии, в то время как метод nextVal() возвращает следующий RecId из кэша(если там еще они есть), либо заставляет Аксапту выделить следующую партиию RecID, поместив их в кэш.


public final void setCacheSize(int _NewSize) – этот метод и устанавливает размер партии, которыми выделяется recID. Если вы планируете вставлять очень много записей, может быть имеет смысл установить размер партии побольше, чтобы не блокировать таблицу SystemSequences.


public final void flushCache( [tableId _tableId = 0] ) - этот метод засавляет Аксапту очистить кэш, в котором хранятся оставшиеся RecID от последнего выделения. Данные RecId можно считать потерянными для Аксапты.


public final int reserveValues(int _nReserved [, tableId _tableId = 0] ) – этот метод засатвляет выделить RecID в количестве _nReserved для Ваших собственных нужд. Метод возвращает значение первого выделенного RecId. При этом Аксапта уже не будет использовать в своих целях ни один из выделенных Вам RecId.


public final void suspendRecIds(tableId _tableId) – подавляет генерацию RecID для определенной таблицы. Теперь при вставке записей в эту таблицу RecId не будет геерироваться автоматически, а обязанность заполнения этого поля ложится на программиста.


public final void removeRecIdSuspension( [tableId _tableId = 0] ) – восстаналивает автоматический процесс генерации RecID для заданной таблицы.


Тепеь вернемся к нашей задаче – заполнении Аксаповских таблиц извне Аксапты или еще точнее генерации RecID для заполняемой таблицы вне Аксапты. Из всех предложенных и рассмотренных мною способов следующий кажется мне наиболее надежным и безопасным:

PHP код:
первыйRecId sysSeq.reserveValues(количество всталяемых записей)
Вызов внешней программы/задачи/хранимой процедуры (первыйRecId, [количество всталяемых записей]) 
То есть, сначала мы резервируем необходимое нам количество RecID, полученомер первого зарезервированного RecID и передаем его в нашу внешнюю программу, подразумевая, что на основе этой информации внешняя программа сама буде генерить RecID.


Очевидно, что у данного метода есть два ограничения:

Должна быть необходимость передавать параметры во внешнюю программу. Если мы вызываем внешний exe-шник, то этот параметр мы можем передать с помощью метода shellExecute класса WinAPI. Вызов хранимой процедуры тоже позволяет передавать в нее параметры.

До вызова внешней программы мы уже должны знать количество вставляемых строк. Иначе, мы просто не будем знать, сколько нам резервировать. Подходы тут могут быть самые разные: или Вы заранее знаете, сколько строк будет вставлено, либо не знаете сколько, но гарантируете, что не больше 100. В этом случае имеет смысл зарезервировать все 100, даже если использованы будут 50. Наконец, это количество может быть вычислено как из Аксапты, так и вызовом той же внешней программы с определенным параметром.


И теперь небольшой пример. Допустим, что у меня на SQL Server’е есть хранимая процедура:

PHP код:
create proc MultipleTable
    
@beginRecId     int
as
  
set nocount on    
  
declare @i int
  set 
@0
  
while (@i<>10)
   
begin
     insert into dem_multi values
(@i*@i'dat', @beginRecId + @i)
     
set @= @1
   end 
А вот пример вызова это хранимой процедуры из Аксапты:

PHP код:
static void Job11(Args _args)
{
    
dem_Multi       multi;
    
Connection      con = new Connection();
    
Statement       stmt con.createStatement();
    
systemSequence  sysSqnc;
    
int             beginRecId;
    ;

    
delete_from multi;

    
sysSqnc = new systemSequence();
    
beginRecId sysSqnc.reserveValues(10);
    
stmt.executeUpdate("exec [Axapta].[dbo].[MultipleTable] " int2str(beginRecId));


За это сообщение автора поблагодарили: mazzy (2), raz (5), Alenka (1), Jolly (1), Crusader3000 (1).
Старый 07.05.2009, 16:49   #2  
ZVV is offline
ZVV
MCITP
MCP
Oracle
MCBMSS
 
1,006 / 246 (11) ++++++
Регистрация: 13.02.2004
Адрес: Минск
->
Предложу свой вариант пакета на PL\SQL реализующий подобные задачи при работе с данными Аксапты извне для Oracle. Написан давно, лет 5 назад, багов вроде не отмечено... Коментариями не "злоупотреблял", вроде в целом всё и так ясно, код несложный. Есть определённые допущения, например хранится только один кэш номеров, для последней компании . Писано для 3.0. Будут вопросы - с удовольствием отвечу.

X++:
CREATE OR REPLACE 
PACKAGE pck_ax_sequence Authid Current_user
Is
   --    RecId
   Procedure P_set_cache_size ( Parm_cache_size In Pls_integer );

   --   Recid
   Function F_nextval ( Parm_dataareaid In Varchar2 )
      Return Number;
End;
/

CREATE OR REPLACE 
Package Body pck_ax_sequence
Is
   L_cache_next_size             Pls_integer := 10;
   L_cache_curr_size             Pls_integer;

   Type T_cache_table Is Table Of Number
      Index By Pls_integer;

   Lt_cache_table                T_cache_table;
   L_index                       Pls_integer;   -- 1 .. L_cache_curr_size
   L_last_dataareaid             Varchar2(5);

   Procedure P_set_cache_size(
      Parm_cache_size            In       Pls_integer)
   As
   Begin
      L_cache_next_size := Parm_cache_size;
   End;

   Procedure P_init(
      Parm_dataareaid            In       Varchar2)
   As
      Pragma Autonomous_transaction;
      L_new_nextval                 Number;
   Begin
      L_cache_curr_size := L_cache_next_size;

      Update    Systemsequences
            Set Nextval = Nextval + L_cache_curr_size
          Where Dataareaid = Parm_dataareaid
            And Recid = -1
            And Name = 'SEQNO'
      Returning Nextval
           Into L_new_nextval;

      L_last_dataareaid := Parm_dataareaid;
      L_index := 1;

      For I In 1 .. L_cache_curr_size Loop
         Lt_cache_table(I) := L_new_nextval - L_cache_curr_size - 1 + I;
      End Loop;

      Commit;
   End;

   Procedure P_check_nextval(
      Parm_dataareaid            In       Varchar2)
   As
   Begin
      If    L_last_dataareaid <> Parm_dataareaid
         Or L_index > L_cache_curr_size
         Or L_index Is Null Then
         P_init(Parm_dataareaid);
      End If;
   End;

   Function F_nextval(
      Parm_dataareaid            In       Varchar2)
      Return Number
   As
   Begin
      P_check_nextval(Parm_dataareaid);
      L_index := L_index + 1;
      Return Lt_cache_table(L_index - 1);
   End;
End;
__________________
Zhirenkov Vitaly
За это сообщение автора поблагодарили: mazzy (2), aidsua (1), Crusader3000 (1).
Теги
ax3.0, faq, recid, systemsequences, t-sql, законченный пример, интеграция, номерная серия, нумерация, полезное

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Кеширование средствами аксапты Logger DAX: Программирование 27 11.10.2007 14:40
Таблицы аксапты и ключевые слова MSSQL zipo DAX: Программирование 12 21.12.2006 20:34
Копирование строк таблицы с помощью DictTable AxPr-r DAX: Программирование 7 29.09.2006 14:35
Свертка строк при выводе из Аксапты в Excel Zabr DAX: Программирование 20 21.02.2006 15:21
Таблицы для PO, SO строк OliaM DAX: Программирование 10 13.11.2004 18:14

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 11:46.