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.aspxdel webCASSANDRA/IEMWeb(operatore/amministratore che disegna una nuova entità). Backend OracleINFOCAD_TEST38, accesso via stored procedure ODP.NET genericaIEM_CREATETABLE(nessun ORM). L'operazione emette DDL dinamico (CREATE TABLE) e registra l'entità nel repository di metadatiIEM_OBJECTS/GLOBAL_TAB_COLUMNS.
- Flow ID: FLOW-IEM-001
- Repository: InfocadWeb (ASP.NET Web Forms, C#,
CASSANDRA/IEMWeb) + InfocadServer (IEMControllers/IEMBL/IEMDAL, VB.NET, hostIEMService/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_SOURCEsuINFOCAD_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 pubblicaIEM_BLvia .NET Remoting (endpointIEM_BL.rem); avviato daStartIEM.Main().- Oracle
INFOCAD_TEST38(hub del modello dati; proceduraIEM_CREATETABLE, funzioneIEM.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#), masterSimpleSD.Master. - Pagina:
IEMWeb/FunctionPages/DataManagement/AddTable.aspx(+ code-behindAddTable.aspx.cs). - Campi input:
rtbTableName(nome tabella,:113),rtbFieldName(nome campo chiave,:122),rcbDataType(tipo dato, filtrato aVARCHAR2/NUMBER,:132),rtbDataLength/rtbDataPrecision/rtbDataScale. - Gate di accesso: autenticazione imposta dalla base
CassandraPage(CassandraPage.cs:22,152); grant utente disponibili viaHasUserGrant(...)(CassandraPage.cs:290,295).
Sequenza principale (main sequence)
- L'amministratore apre
AddTable.aspx, inserisce nome tabella, nome campo chiave, sceglie il tipo dato e preme Salva. - Validazione lato server (vedi § Validazione):
cvTableName_ServerValidateverifica che la tabella non esista già (ctrl.TableExists,AddTable.aspx.cs:316);cvFieldName_ServerValidatevalida il nome campo con regex Oracle-compatibile (:323). btnSave_Click(AddTable.aspx.cs:118) converte i parametri numerici, impostaisAutomaticCount = 1se il tipo èNUMBER(:161), e chiamactrl.CreateTable(tableName, fieldName, dataType, dataLength, dataPrecision, dataScale, "", 0, 1, 0, isAutomaticCount, 0)(:163). Nota:primaryKeyè forzato a1(terzultimo→primaryKey=1) esystemTable=0.IEMController.CreateTable(IEMController.vb:124) inoltra al DAO remoto:DirectCast(Me.DAO, IIEM_BL).CreateTable(...).Me.DAOè ottenuto daDAOFactory.CreateDAO(enControllers.Ctrl_IEM)(Ctrl_Base.vb:6-8), che viaActivator.GetObject(GetType(IIEM_BL), CHANNEL://SERVERADDRESS/IEM_BL.rem)restituisce un proxy .NET Remoting versoIEM_BLospitato inIEMService/IEMServer(DAOFactory.vb:12,ServicesDictionary.resx: Service_IEM = "IEM_BL.rem").
IEM_BL.CreateTable(IEM_BL.vb:208-221) inoltra al DAL:IEMDALFactory.GetIEMDAL().CreateTable(...).IEM_DAL.CreateTable(IEM_DAL.vb:490) apreUsing dl As New DataLayer(My.Settings.ConnectionName), prepara i parametri Oracle (PTABLENAME,PFIELDNAME,PDATATYPE,PDATALENGTH,PDATAPRECISION,PDATASCALE,PDEFAULTVALUE,PNULLVALUES,PPRIMARYKEY,PSYSTEMTABLE,PISAUTOMATICCOUNT,PISCOUNTFROMSEQ+POUTOUTDecimal) e invocadl.ExecuteNonQueryStoredProcedure("IEM_CREATETABLE")(:523); legge il ritorno daPOUT(:524).- 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_LOGe lo esegue conEXECUTE 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 triggerCNT_<tabella>di autoincremento del campo chiave (src:96-121); - se
PISCOUNTFROMSEQ=1: crea (se manca)SEQ_<tabella>viaIEM.SEQUEXISTSe trigger da sequence (src:125-162); - registra il campo chiave come campo di sistema in
GLOBAL_TAB_COLUMNS(src:166-169); POUT := 1in caso di successo (src:173-175);WHEN OTHERS⇒POUT := 0(src:177-181).
- risolve lo schema corrente (
- Il DAL restituisce
POUTcomeInteger(IEM_DAL.vb:524), risalendo BL → controller → code-behind. btnSave_Clickvaluta il ritorno: seres == 1esegueClose()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 ottieneIEM_BLcome oggetto remoto (Activator.GetObject, endpointIEM_BL.rem) esposto dal servizio IEM (IEMService/IEMServer, avvioStartIEM.Main()).
Backend
- UI/Code-behind:
AddTable.aspx/AddTable.aspx.cs(CASSANDRA/IEMWeb). - Controller (client-side, nel web):
Descor.IEM.IEMControllers.IEMController(IEMController.vb), baseCtrl_EntityBase/Ctrl_BaseconDAOrisolto daDAOFactory. - Business layer (remoto, nel servizio):
Descor.IEM.IEMBL.IEM_BL(IEM_BL.vb), inoltra aIEMDALFactory. - 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 OUTPOUT(Decimal, 0/1). - Host servizio:
IEMServer(Windows Service,IEMServer.vb) eIEMService(console C#,Program.cs), entrambi avvianoDescor.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 daIEM.SEQUEXISTS(verifica esistenza sequence) e dal pre-checkIEM_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_OBJECTS—INSERT(registrazione entità nel repository IEM) (src:82-93).INFOCAD_TEST38.GLOBAL_TAB_COLUMNS—INSERT(campo chiave come campo di sistema) (src:166-169).INFOCAD_TEST38.GLOBAL_DEBUG_LOG—INSERT(log del DDL/trigger eseguiti) (src:70-71,113-114,156-157).- Trigger
CNT_<tabella>e/o sequenceSEQ_<tabella>—CREATE OR REPLACEcondizionali (src:96-162).
Validazione
- Lato UI (server-side):
RequiredFieldValidatorsu nome tabella, campo, tipo dato (AddTable.aspx:114,123,141).cvTableName_ServerValidate(AddTable.aspx.cs:309): rifiuta sectrl.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 dibtnSave_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 OTHERScattura e restituiscePOUT=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_LOGcon 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 OTHERS⇒POUT=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_BLlogga viaExceptionLoggere in alcune Action ingoia l'eccezione (IEM_BL.vb), maCreateTablefaThrowdal 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_Click → ctrl.CreateTable |
AddTable.aspx.cs:118,163 ; validazioni :309,323 |
| Base sicurezza | CassandraPage (auth) |
CASSANDRA/Authentication/CassandraPage.cs:22,152,290 |
| Controller (web) | IEMController.CreateTable → DAO |
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.CreateTable → IEMDALFactory |
IEM_BL.vb:208,221 |
| DAL | IEM_DAL.CreateTable → IEM_CREATETABLE |
IEM_DAL.vb:490,507-518,523,524 |
| Host servizio | IEMServer / IEMService → StartIEM.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 daIEM_DAL.CreateTable(IEM_DAL.vb:523).IEM_DAL.CreateTable←IEM_BL.CreateTable(IEM_BL.vb:221) ←IEMController.CreateTable(IEMController.vb:124) ←ctrl.CreateTable(...)nel code-behindAddTable.aspx.cs:163.- Unici chiamanti di
ctrl.CreateTable(...)nel codice:CASSANDRA/IEMWeb/.../AddTable.aspx.cs:163e la copia legacyWebMachine/IEM/.../AddTable.aspx.cs:159(stesso identico pattern). - Forward e reverse concordano: la pagina
AddTable.aspx→CreateTable→IEM_CREATETABLEconCREATE TABLE+ INSERT suIEM_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_CREATETABLEletto daALL_SOURCEsuINFOCAD_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 daDAOFactory+ServicesDictionary+ hostIEMService/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 (
HasUserGrantnon risulta invocato inAddTable.aspx.cs). - Feedback all'utente quando
IEM_CREATETABLEritornaPOUT=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/IEMWebe la copia legacyWebMachine/IEM(quale sia effettivamente mappato in IIS/CASSANDRA a runtime). - Valori esatti passati a runtime per
PISCOUNTFROMSEQ(sempre 0 dal pathAddTable, quindi il ramo sequence non è esercitato da questa pagina).