Table of Contents

FLOW-IEM-001 — Creazione di una nuova tabella/entità del modello dati — IEM (Infocad Entity Manager)

Flusso end-to-end di creazione di una nuova tabella (entità) del modello dati tramite il modulo IEM (Infocad Entity Manager), lo strumento di amministrazione/design del data model di Infocad. Path pilota: pagina AddTable.aspx del web CASSANDRA/IEMWeb (operatore/amministratore che disegna una nuova entità). Backend Oracle INFOCAD_TEST38, accesso via stored procedure ODP.NET generica IEM_CREATETABLE (nessun ORM). L'operazione emette DDL dinamico (CREATE TABLE) e registra l'entità nel repository di metadati IEM_OBJECTS / GLOBAL_TAB_COLUMNS.

  • Flow ID: FLOW-IEM-001
  • Repository: InfocadWeb (ASP.NET Web Forms, C#, CASSANDRA/IEMWeb) + InfocadServer (IEMControllers/IEMBL/IEMDAL, VB.NET, host IEMService/IEMServer)
  • Confidence complessiva: VERIFIED (catena UI → code-behind → controller → BL remoto → DAL → nome stored procedure confermata sul codice e sorgente della stored procedure letto da ALL_SOURCE su INFOCAD_TEST38)

Significato del dominio IEM

IEM = Infocad Entity Manager: modulo di amministrazione/design del modello dati. Non gestisce dati anagrafici di business, ma la struttura del database applicativo e i suoi metadati. Le operazioni esposte (dal controller IEMController / interfaccia IIEM_BL) sono tipicamente di scrittura DDL o di metadati: creare tabelle (CreateTable) e campi (CreateField/ModifyField/DeleteField), aggiungere campi alle viste (AddFieldsToViews), definire campi calcolati e formule (AddCalculatedFields/SaveFormula), gestire tabelle esterne (AddExternalTables), sezioni/etichette di scheda (UpdateSection/UpdateSorting/UpdateLabelOrder), compilare oggetti PL/SQL (CompileObject/CompileAll), popolare l'archivio (PopulateArchive) ed eseguire script (CreateScript). Esiste quindi un percorso di scrittura autonomo e chiaro: la creazione di una tabella è l'operazione WRITE più rappresentativa e autocontenuta del dominio.

Obiettivo di business

Consentire a un amministratore/progettista del modello dati di creare una nuova entità (tabella Oracle) con il relativo campo chiave, direttamente dalla UI di IEM. Al termine dell'operazione: la tabella fisica esiste nello schema INFOCAD_TEST38, l'entità è registrata nel repository metadati IEM_OBJECTS (così da comparire nell'albero oggetti di IEM), il campo chiave è registrato in GLOBAL_TAB_COLUMNS, e — a seconda delle opzioni — viene creato un trigger di conteggio automatico del campo chiave (eventualmente con sequence dedicata).

Attori

  • Amministratore / progettista del modello dati (utente autenticato sulla shell CASSANDRA; la pagina eredita da CassandraPage, che impone l'autenticazione — redirect al login se assente).
  • IEMService / IEMServer — host del business layer IEM (servizio Windows / console) che pubblica IEM_BL via .NET Remoting (endpoint IEM_BL.rem); avviato da StartIEM.Main().
  • Oracle INFOCAD_TEST38 (hub del modello dati; procedura IEM_CREATETABLE, funzione IEM.SEQUEXISTS), con esecuzione di DDL dinamico e scritture sui repository di metadati.

Trigger

Click sul pulsante Salva (btnSave) della pagina modale AddTable.aspx: evento OnClick="btnSave_Click" (markup AddTable.aspx:229), gestito da btnSave_Click (AddTable.aspx.cs:118). La pagina è aperta come RadWindow dai controlli dell'albero/filtri di gestione tabelle (TablesManagementFilters.ascx:61, ObjectTreeView.ascx:45).

Frontend entry point

  • Web app: CASSANDRA/IEMWeb (ASP.NET Web Forms, C#), master SimpleSD.Master.
  • Pagina: IEMWeb/FunctionPages/DataManagement/AddTable.aspx (+ code-behind AddTable.aspx.cs).
  • Campi input: rtbTableName (nome tabella, :113), rtbFieldName (nome campo chiave, :122), rcbDataType (tipo dato, filtrato a VARCHAR2/NUMBER, :132), rtbDataLength/rtbDataPrecision/ rtbDataScale.
  • Gate di accesso: autenticazione imposta dalla base CassandraPage (CassandraPage.cs:22,152); grant utente disponibili via HasUserGrant(...) (CassandraPage.cs:290,295).

Sequenza principale (main sequence)

  1. L'amministratore apre AddTable.aspx, inserisce nome tabella, nome campo chiave, sceglie il tipo dato e preme Salva.
  2. Validazione lato server (vedi § Validazione): cvTableName_ServerValidate verifica che la tabella non esista già (ctrl.TableExists, AddTable.aspx.cs:316); cvFieldName_ServerValidate valida il nome campo con regex Oracle-compatibile (:323).
  3. btnSave_Click (AddTable.aspx.cs:118) converte i parametri numerici, imposta isAutomaticCount = 1 se il tipo è NUMBER (:161), e chiama ctrl.CreateTable(tableName, fieldName, dataType, dataLength, dataPrecision, dataScale, "", 0, 1, 0, isAutomaticCount, 0) (:163). Nota: primaryKey è forzato a 1 (terzultimo→primaryKey=1) e systemTable=0.
  4. IEMController.CreateTable (IEMController.vb:124) inoltra al DAO remoto: DirectCast(Me.DAO, IIEM_BL).CreateTable(...).
    • Me.DAO è ottenuto da DAOFactory.CreateDAO(enControllers.Ctrl_IEM) (Ctrl_Base.vb:6-8), che via Activator.GetObject(GetType(IIEM_BL), CHANNEL://SERVERADDRESS/IEM_BL.rem) restituisce un proxy .NET Remoting verso IEM_BL ospitato in IEMService/IEMServer (DAOFactory.vb:12, ServicesDictionary.resx: Service_IEM = "IEM_BL.rem").
  5. IEM_BL.CreateTable (IEM_BL.vb:208-221) inoltra al DAL: IEMDALFactory.GetIEMDAL().CreateTable(...).
  6. IEM_DAL.CreateTable (IEM_DAL.vb:490) apre Using dl As New DataLayer(My.Settings.ConnectionName), prepara i parametri Oracle (PTABLENAME, PFIELDNAME, PDATATYPE, PDATALENGTH, PDATAPRECISION, PDATASCALE, PDEFAULTVALUE, PNULLVALUES, PPRIMARYKEY, PSYSTEMTABLE, PISAUTOMATICCOUNT, PISCOUNTFROMSEQ + POUT OUT Decimal) e invoca dl.ExecuteNonQueryStoredProcedure("IEM_CREATETABLE") (:523); legge il ritorno da POUT (:524).
  7. Oracle IEM_CREATETABLE (INFOCAD_TEST38, procedura standalone):
    • risolve lo schema corrente (SYS_CONTEXT('USERENV','CURRENT_SCHEMA'), src:25-27);
    • costruisce il DDL CREATE TABLE <PTABLENAME> (<PFIELDNAME> <tipo>[…][DEFAULT][NOT NULL][, CONSTRAINT …PK PRIMARY KEY]) (src:30-68);
    • logga il DDL in GLOBAL_DEBUG_LOG e lo esegue con EXECUTE IMMEDIATE (src:70-76);
    • registra l'entità nel repository IEM_OBJECTS (id = MAX(ID_N)+1, OBJECTTYPE='TABLE', ISSYSTEM=PSYSTEMTABLE, ISVISIBLE=1) (src:79-93);
    • se PISAUTOMATICCOUNT=1: crea trigger CNT_<tabella> di autoincremento del campo chiave (src:96-121);
    • se PISCOUNTFROMSEQ=1: crea (se manca) SEQ_<tabella> via IEM.SEQUEXISTS e trigger da sequence (src:125-162);
    • registra il campo chiave come campo di sistema in GLOBAL_TAB_COLUMNS (src:166-169);
    • POUT := 1 in caso di successo (src:173-175); WHEN OTHERSPOUT := 0 (src:177-181).
  8. Il DAL restituisce POUT come Integer (IEM_DAL.vb:524), risalendo BL → controller → code-behind.
  9. btnSave_Click valuta il ritorno: se res == 1 esegue Close() lato client per chiudere la modale (AddTable.aspx.cs:179).

API / service

  • Path UI: postback ASP.NET Web Forms diretto sulla pagina AddTable.aspx (nessun SOAP/WCF nel path).
  • Trasporto verso il backend: .NET Remoting (non WCF, non in-process). Il web istanzia IEMControllers.IEMController (AddTable.aspx.cs:22); il controller ottiene IEM_BL come oggetto remoto (Activator.GetObject, endpoint IEM_BL.rem) esposto dal servizio IEM (IEMService/IEMServer, avvio StartIEM.Main()).

Backend

  • UI/Code-behind: AddTable.aspx / AddTable.aspx.cs (CASSANDRA/IEMWeb).
  • Controller (client-side, nel web): Descor.IEM.IEMControllers.IEMController (IEMController.vb), base Ctrl_EntityBase/Ctrl_Base con DAO risolto da DAOFactory.
  • Business layer (remoto, nel servizio): Descor.IEM.IEMBL.IEM_BL (IEM_BL.vb), inoltra a IEMDALFactory.
  • DAL: Descor.IEM.IEMDAL.OracleODP.IEM_DAL (IEM_DAL.vb).
  • Pattern DAL: Using dl As New DataLayer(My.Settings.ConnectionName)dl.Parameters.Add(OracleParameter…)dl.ExecuteNonQueryStoredProcedure("IEM_CREATETABLE"); esito via parametro OUT POUT (Decimal, 0/1).
  • Host servizio: IEMServer (Windows Service, IEMServer.vb) e IEMService (console C#, Program.cs), entrambi avviano Descor.Infrastructure.Business.StartIEM.Main().

Query / stored procedure

Passo Stored procedure / oggetto (Oracle) Chiamata da (DAL)
Creazione tabella + registrazione metadati (DDL dinamico su nuova tabella) INFOCAD_TEST38.IEM_CREATETABLE (OUT POUT 0/1) IEM_DAL.vb:523
Verifica esistenza sequence (dentro IEM_CREATETABLE) INFOCAD_TEST38.IEM.SEQUEXISTS IEM_CREATETABLE src:129
Validazione: la tabella esiste già? (pre-check UI) INFOCAD_TEST38.IEM_EXISTSTAB IEM_DAL.vb:206
Popolamento combo tipi dato (READ-ONLY) INFOCAD_TEST38.IEM_GETPROPERTIESFIELD IEM_DAL.vb:152

Tabelle lette (read)

  • INFOCAD_TEST38: DUAL; IEM_OBJECTS (SELECT MAX(ID_N)+1, src:79-81); cataloghi Oracle usati indirettamente da IEM.SEQUEXISTS (verifica esistenza sequence) e dal pre-check IEM_EXISTSTAB (USER_TABLES, non nel path di scrittura ma nella validazione UI).

Tabelle modificate (write)

  • INFOCAD_TEST38.(nuova tabella <PTABLENAME>)CREATE TABLE … EXECUTE IMMEDIATE (src:30-76) — DDL, entità creata.
  • INFOCAD_TEST38.IEM_OBJECTSINSERT (registrazione entità nel repository IEM) (src:82-93).
  • INFOCAD_TEST38.GLOBAL_TAB_COLUMNSINSERT (campo chiave come campo di sistema) (src:166-169).
  • INFOCAD_TEST38.GLOBAL_DEBUG_LOGINSERT (log del DDL/trigger eseguiti) (src:70-71,113-114,156-157).
  • Trigger CNT_<tabella> e/o sequence SEQ_<tabella>CREATE OR REPLACE condizionali (src:96-162).

Validazione

  • Lato UI (server-side):
    • RequiredFieldValidator su nome tabella, campo, tipo dato (AddTable.aspx:114,123,141).
    • cvTableName_ServerValidate (AddTable.aspx.cs:309): rifiuta se ctrl.TableExists(nome.ToUpper()) è vero (:301) → messaggio "Nome tabella già esistente".
    • cvFieldName_ServerValidate (AddTable.aspx.cs:323): regex ^[A-Z]{1,1}[A-Z0-9#_$]{1,30}$ (nome maiuscolo, inizia con lettera, max 30+1 caratteri, set Oracle-compatibile) (:319-325).
    • if (!IsValid) return; all'inizio di btnSave_Click (:120).
  • Lato DB: la procedura non ripete i controlli di validità del nome; in caso di errore DDL (nome duplicato, sintassi, privilegi) l'handler WHEN OTHERS cattura e restituisce POUT=0 (src:177-181) — nessuna eccezione propagata al chiamante, l'esito è solo il codice 0/1.

Side effects

  • DDL fisico: creazione di una tabella Oracle e (opzionale) di trigger/sequence — modifica permanente dello schema INFOCAD_TEST38.
  • COMMIT multipli interni alla procedura dopo ogni step (src:72,76,93,115,119,158,161): l'operazione non è atomica — un fallimento tardivo può lasciare tabella creata ma metadati parziali.
  • Log applicativo: ogni statement DDL/trigger è tracciato in GLOBAL_DEBUG_LOG con utente e data.
  • Effetto UI: l'entità appare nell'albero oggetti IEM (via IEM_OBJECTS).

Percorsi alternativi / errore

  • Nome tabella già esistente: bloccato in validazione UI (TableExists) prima della chiamata.
  • Errore DDL a runtime (privilegi mancanti, nome riservato, limiti Oracle): WHEN OTHERSPOUT=0; il code-behind non chiude la modale (res != 1) ma non mostra un messaggio d'errore esplicito (open question sul feedback all'utente).
  • Backend IEM non raggiungibile (.NET Remoting): eccezione a livello controller/DAL; IEM_BL logga via ExceptionLogger e in alcune Action ingoia l'eccezione (IEM_BL.vb), ma CreateTable fa Throw dal DAL (IEM_DAL.vb:533).
  • Operazioni analoghe del dominio (stesso pattern controller→BL remoto→DAL→SP): CreateField (IEM_CREATEFIELD), AddCalculatedFields, SaveFormula, AddExternalTables, PopulateArchive, CompileObject.

Diagramma di sequenza (Mermaid)

sequenceDiagram
    actor Adm as Amministratore modello dati
    participant UI as AddTable.aspx (IEMWeb)
    participant CB as AddTable.aspx.cs
    participant CT as IEMController (web)
    participant RM as .NET Remoting (IEM_BL.rem)
    participant BL as IEM_BL (IEMService)
    participant DAL as IEM_DAL
    participant DB as Oracle INFOCAD_TEST38

    Adm->>UI: Compila nome/campo/tipo, click Salva
    UI->>CB: btnSave_Click
    CB->>CB: IsValid? (TableExists, regex campo)
    CB->>CT: ctrl.CreateTable(...)
    CT->>RM: DirectCast(DAO, IIEM_BL).CreateTable(...)
    RM->>BL: CreateTable(...)
    BL->>DAL: IEMDALFactory.GetIEMDAL().CreateTable(...)
    DAL->>DB: ExecuteNonQueryStoredProcedure("IEM_CREATETABLE")
    DB->>DB: EXECUTE IMMEDIATE 'CREATE TABLE ...'
    DB->>DB: INSERT IEM_OBJECTS / GLOBAL_TAB_COLUMNS / GLOBAL_DEBUG_LOG
    alt PISAUTOMATICCOUNT=1 / PISCOUNTFROMSEQ=1
        DB->>DB: CREATE TRIGGER CNT_<t> [+ SEQ_<t>]
    end
    DB-->>DAL: POUT (1 successo | 0 errore)
    DAL-->>BL: res
    BL-->>CT: res
    CT-->>CB: res
    CB-->>Adm: res==1 ⇒ Close() (chiude modale)

Matrice di tracciabilità

Layer Artefatto Evidenza (file:riga)
UI AddTable.aspx (campi + btnSave) IEMWeb/FunctionPages/DataManagement/AddTable.aspx:113,122,132,229
Apertura modale TablesManagementFilters.ascx / ObjectTreeView.ascx TablesManagementFilters.ascx:61 ; ObjectTreeView.ascx:45
Code-behind btnSave_Clickctrl.CreateTable AddTable.aspx.cs:118,163 ; validazioni :309,323
Base sicurezza CassandraPage (auth) CASSANDRA/Authentication/CassandraPage.cs:22,152,290
Controller (web) IEMController.CreateTableDAO IEMController.vb:124
Factory DAO DAOFactory.CreateDAO(Ctrl_IEM) (Remoting) DAOFactory.vb:12 ; Ctrl_Base.vb:6,11 ; ServicesDictionary.resx:123
BL (remoto) IEM_BL.CreateTableIEMDALFactory IEM_BL.vb:208,221
DAL IEM_DAL.CreateTableIEM_CREATETABLE IEM_DAL.vb:490,507-518,523,524
Host servizio IEMServer / IEMServiceStartIEM.Main() IEMServer.vb:11 ; IEMService/Program.cs:33
DB IEM_CREATETABLE (DDL + metadati) ALL_SOURCE IEM_CREATETABLE src:1-13,30-93,166-181
DB (scritture) IEM_OBJECTS, GLOBAL_TAB_COLUMNS, GLOBAL_DEBUG_LOG INSERT src:82-93,166-169,70-71
DB (trigger/seq) CNT_<t> / SEQ_<t> (IEM.SEQUEXISTS) src:96-162
DB (catalogo) IEM_CREATETABLE PROCEDURE di INFOCAD_TEST38 ; tabelle target esistono database-catalog.json (PROCEDURE + TABLE)

Reverse trace (dal DB/controller ai chiamanti)

  • IEM_CREATETABLE è invocata esclusivamente da IEM_DAL.CreateTable (IEM_DAL.vb:523).
  • IEM_DAL.CreateTableIEM_BL.CreateTable (IEM_BL.vb:221) ← IEMController.CreateTable (IEMController.vb:124) ← ctrl.CreateTable(...) nel code-behind AddTable.aspx.cs:163.
  • Unici chiamanti di ctrl.CreateTable(...) nel codice: CASSANDRA/IEMWeb/.../AddTable.aspx.cs:163 e la copia legacy WebMachine/IEM/.../AddTable.aspx.cs:159 (stesso identico pattern).
  • Forward e reverse concordano: la pagina AddTable.aspxCreateTableIEM_CREATETABLE con CREATE TABLE + INSERT su IEM_OBJECTS/GLOBAL_TAB_COLUMNS. NO CONFLICTING.

Evidenza (file:line)

Punti chiave (codice): AddTable.aspx:113,122,132,229; AddTable.aspx.cs:22,118,120,161,163,179,309,316,323,330; CassandraPage.cs:22,152,290; IEMController.vb:124; DAOFactory.vb:12; Ctrl_Base.vb:6,11; ServicesDictionary.resx:123 (Service_IEM=IEM_BL.rem); IEM_BL.vb:208,221; IEM_DAL.vb:490,507-518,523,524,533; IEMServer.vb:11; IEMService/Program.cs:33.

Punti chiave (DB, INFOCAD_TEST38, letti in sola lettura via ALL_SOURCE/ALL_OBJECTS): IEM_CREATETABLE firma src:1-13; DDL dinamico CREATE TABLE src:30-68; log+exec src:70-76; INSERT IEM_OBJECTS src:79-93; trigger conteggio automatico src:96-121; sequence+trigger src:125-162 (con IEM.SEQUEXISTS src:129); INSERT GLOBAL_TAB_COLUMNS src:166-169; esito POUT=1/WHEN OTHERS POUT=0 src:173-181. Catalogo: IEM_CREATETABLE è PROCEDURE standalone di INFOCAD_TEST38 (database-catalog.json → object_names_by_type/PROCEDURE); IEM_OBJECTS, GLOBAL_TAB_COLUMNS, GLOBAL_DEBUG_LOG sono TABLE esistenti nello schema.

Confidence

  • VERIFIED: catena UI → code-behind → controller → BL (remoto) → DAL → nome stored procedure (letta sui sorgenti) e sorgente della stored procedure IEM_CREATETABLE letto da ALL_SOURCE su INFOCAD_TEST38 (CREATE TABLE dinamico, INSERT metadati, esito 0/1); esistenza procedura e tabelle target dal catalogo. Due tipi di evidenza indipendenti (codice + DB live).
  • SUPPORTED: significato del dominio IEM (Entity Manager) dedotto dall'insieme coerente delle operazioni del controller IIEM_BL; trasporto .NET Remoting dedotto da DAOFactory + ServicesDictionary + host IEMService/IEMServer (nessun test runtime eseguito).
  • INFERRED: comportamento del feedback UI in caso di errore DDL (nessun messaggio esplicito visto); logica interna di IEM.SEQUEXISTS (non ispezionata riga per riga).

Open questions

  • Come viene applicato il grant/ruolo specifico per l'accesso alla funzione IEM oltre alla semplice autenticazione (HasUserGrant non risulta invocato in AddTable.aspx.cs).
  • Feedback all'utente quando IEM_CREATETABLE ritorna POUT=0 (errore DDL): la modale resta aperta ma non si è individuato un messaggio d'errore esplicito.
  • Non-atomicità: i COMMIT intermedi nella procedura possono lasciare stato parziale (tabella creata ma metadati incompleti) in caso di errore tardivo — gestione/compensazione non definita nel codice visto.
  • Coesistenza tra il web attuale CASSANDRA/IEMWeb e la copia legacy WebMachine/IEM (quale sia effettivamente mappato in IIS/CASSANDRA a runtime).
  • Valori esatti passati a runtime per PISCOUNTFROMSEQ (sempre 0 dal path AddTable, quindi il ramo sequence non è esercitato da questa pagina).