FLOW-EXP-001 — Registrazione di un job di export nello spooler — ExportService
Flusso end-to-end di registrazione/avvio di un job di export asincrono del dominio ExportService. L'operazione rappresentativa di scrittura autonoma è la registrazione del job nello spooler: il client (WCF
ApplicationService.svc) chiama, tramite .NET Remoting, il servizio WindowsExportService, che invoca la stored procedure OracleRPS_SETSPOOLER_LASTQUERY. Questa esegue unMERGE(INSERT/UPDATE) sulla tabellaGLOBAL_SPOOLER(INFOCAD_TEST38), creando la riga di spooler in stato in coda (STATUS = 0) con nome export, SQL di estrazione e scadenza. Nessun ORM. Il job di export vero e proprio ne aggiorna poi lo stato (RPS_SETSPOOLER_STATUS) durante il ciclo di vita.
- Flow ID: FLOW-EXP-001
- Repository: InfocadServer (ExportService / ExportServiceControllers / ExportServiceInterface, C#; DocumentDAL, VB.NET) + InfocadWeb (WCF
ApplicationService.svc, C#) - Confidence complessiva: VERIFIED (catena WCF → controller Remoting → servizio → DAL
Execute*StoredProcedure→ stored procedure, confermata su codice E su sorgente DBUSER_SOURCE; mappa suGLOBAL_SPOOLERconfermata suUSER_TAB_COLUMNS/USER_DEPENDENCIES) - has_standalone_write:
true— la registrazione dello spooler (RPS_SETSPOOLER_LASTQUERY→ INSERT/UPDATEGLOBAL_SPOOLER) è una scrittura autonoma del dominio; l'aggiornamento di stato (RPS_SETSPOOLER_STATUS) è la seconda scrittura del ciclo di vita.
Obiettivo di business
Consentire a un utente autenticato di richiedere l'esportazione asincrona di un insieme di dati (griglia DataView, immagini, documenti/PDF) senza bloccare la sessione web. La richiesta viene materializzata come "job" persistente in una coda (spooler): al termine l'utente troverà nella propria area un file scaricabile. La registrazione crea/aggiorna la riga di spooler dell'utente in stato in coda, memorizzando nome dell'export, query SQL di estrazione, chiavi e conteggio righe.
Attori
- Utente autenticato (operatore su un DataView/griglia, area documenti, ecc.) — path interattivo web.
- Client WCF
ApplicationService.svc(WebMachine CASSANDRA / IEM) — orchestratore lato web che registra il job e poi ne avvia l'esecuzione. - Servizio Windows
ExportService(host Remoting registrato inBusiness/Start.vb) — esegue la scrittura DB e ospita i job di export (DataViewExportReader,ImagesExportReader,DocumentsPDFJob…). - Oracle
INFOCAD_TEST38— hub anagrafico: tabellaGLOBAL_SPOOLER(coda job) e procedureRPS_*; risoluzione utente/tenant cross-schema suASPNET_TEST38.ORA_ASPNET_USERS/APPLICATIONS.
Trigger
Chiamata WCF a un metodo di export di ApplicationService.svc, es. ExportImagesData
(ApplicationService.svc.cs:170) o ExportDocumentsData (:184), che per prima cosa registra
il job via ExportServiceController.SetSpooler_LastQuery(...)
(ApplicationService.svc.cs:175,189,203). Per l'export della griglia DataView la registrazione
avviene a monte (impostazione dell'ultima query), poi ExportData (:148) avvia soltanto
l'esecuzione leggendo la riga di spooler già in stato 0.
Frontend entry point
- Servizio WCF:
InfocadWeb/WebMachine/CASSANDRA/WebServices/ApplicationService.svc.cs(contrattoIApplicationService), metodiExportData(:148),ExportDocument(:156),ExportImagesData(:170),ExportDocumentsData(:184),ExportDocumentsDataZip(:198). - Gate di accesso:
ValidateToken(token: request.UserName)all'ingresso di ogni metodo (ApplicationService.svc.cs:150,158,172,186,200) — risolve/valida l'utente dal token.
Sequenza principale (main sequence)
- Il client web invoca
ApplicationService.ExportImagesData(request)(:170);ValidateTokenvalida l'utente (:172). - Il metodo istanzia
ExportServiceControllereDataViewExportController(:173-174) e registra il job:ctrl.SetSpooler_LastQuery(request.UserName, request.Procedure, string.Empty)(:175). ExportServiceController.SetSpooler_LastQuery(ExportServiceController.cs:53) inoltra via .NET Remoting al servizioExportService(proxy creato nel costruttore, canale…/ExportService.rem,ExportServiceController.cs:17).ExportService.SetSpooler_LastQuery(ExportService.cs:298) prepara i parametri Oracle (PUSERNAME,PNAME,PSQL) e chiamadl.ExecuteNonQueryStoredProcedure("RPS_SETSPOOLER_LASTQUERY")(ExportService.cs:312).- Oracle
RPS_SETSPOOLER_LASTQUERY(INFOCAD_TEST38):- risolve
USERID(RAW) dell'utente daASPNET_TEST38.ORA_ASPNET_USERS/APPLICATIONSfiltrando perLOWER(USER)(schema applicativo) eLOWEREDUSERNAME(src:17-23); - se
PKEYSvalorizzato, calcola il conteggio righe conEXECUTE IMMEDIATE 'SELECT COUNT(1) FROM (…)'(src:12-15); - esegue un
MERGE INTO GLOBAL_SPOOLERcon chiave(USERID, STATUS = 0)(src:25-34):- WHEN NOT MATCHED → INSERT
(USERID, EXPORTNAME, STATUS=0, EXPORTDATA=PSQL, STARTDATE=SYSDATE, EXPIREDATE=SYSDATE+1, EXPORTKEYS, EXPORTTOTAL)(src:29-32) — nuova riga di spooler in coda; - WHEN MATCHED → UPDATE dei campi export sulla riga in coda esistente (
src:33-34).
- WHEN NOT MATCHED → INSERT
- risolve
- Registrato il job, il metodo WCF ne avvia l'esecuzione:
dv_ctrl.StartExport(request.UserName, ExportType.IMAGES, …)(ApplicationService.svc.cs:177). DataViewService.PrepareExcelJobForExecution/PrepareJobForExecutionlegge la riga appena creata conRPS_GETSPOOLER_INFO(DataViewService.cs:37,110): conPIDSPOOLERNULL la SP restituisce la riga dell'utente inSTATUS = 0(RPS_GETSPOOLER_INFO src:24-30), da cui si ricavaID_SPOOLER.- Il reader parte (
export.Start(),DataViewService.cs:85,147) e, inBaseGetData, marca il job in esecuzione:_ctrl.SetSpooler_Status(idspooler, 1, "")→RPS_SETSPOOLER_STATUS(DataViewExportReader.cs:48;ExportService.cs:344,358)._ctrlè un'istanza in-process diExportService(DataViewDataReaderJob.cs:45). - Al completamento:
_ctrl.SetSpooler_Progress(idspooler, 100)(DataViewDataReaderJob.cs:192) e_ctrl.SetSpooler_Status(idspooler, 2, fileName)(DataViewDataReaderJob.cs:206) → il job è completato con il nome file prodotto. - Oracle
RPS_SETSPOOLER_STATUS:UPDATE GLOBAL_SPOOLER SET STATUS = :PSTATUS, FILENAME = COALESCE(:PFILENAME, FILENAME) WHERE ID_SPOOLER = :PIDSPOOLER(src:7-9). - L'utente scarica poi il file (
ExportService.ExportFileBytes,ExportService.cs:70) e/o consulta lo stato spooler; i job scaduti vengono ripuliti daCleanExport(ExportService.cs:32).
API / service
- Ingresso web (SOAP/WCF):
ApplicationService.svc— metodiExportData/ExportDocument/ExportImagesData/ExportDocumentsData/ExportDocumentsDataZip. - Servizio applicativo (Remoting,
SingleCall):ExportService,DataViewService,DocumentService,MaintenanceService, registrati inBusiness/Start.vb:999+(es.DataViewExportService.rem,ExportService.rem). - Controller proxy (client Remoting):
ExportServiceController,DataViewExportController,DocumentExportController,MaintenanceExportController(ExportServiceControllers/).
Backend
- Orchestratore web:
ApplicationService.svc.cs(C#). - Interfaccia servizio:
Descor.ExportServiceInterface.IExportService/IDataViewService(ExportServiceInterface/). - Controller (proxy Remoting):
Descor.ExportServiceControllers.ExportServiceController(ExportServiceControllers/ExportServiceController.cs), costruito conActivator.GetObject(typeof(IExportService), CHANNEL + "://" + SERVERADDRESS + "/ExportService.rem"). - Servizio (DAO):
Descor.ExportService.ExportService : MarshalByRefObject, IExportService(ExportService/ExportService.cs) e sottoclasseDataViewService(ExportService/DataViewService.cs). - Job:
DataViewDataReaderJob/DataViewExportReader(Excel),ImagesExportReader,DocumentsPDFJob/DocumentsZipJob(ExportService/Deployment/**). - Pattern DAL:
new DataLayer(Properties.Settings.Default.ConnectionName)→dl.Parameters.Add(new OracleParameter(...))→dl.ExecuteNonQueryStoredProcedure("RPS_…")(ODP.NET,Oracle.DataAccess.Client). Nessun ORM.
Query / stored procedure
| Passo | Stored procedure (Oracle) | Chiamata da (DAL) |
|---|---|---|
Registrazione job (INSERT/UPDATE GLOBAL_SPOOLER) |
INFOCAD_TEST38.RPS_SETSPOOLER_LASTQUERY (MERGE) |
ExportService.cs:312 |
| Lettura riga spooler (get ID_SPOOLER) | INFOCAD_TEST38.RPS_GETSPOOLER_INFO |
DataViewService.cs:37,110 |
| Estrazione dati da esportare (READ) | INFOCAD_TEST38.RPS_GETSPOOLER_QUERY |
DataViewExportReader.cs:78 |
Aggiornamento stato job (UPDATE GLOBAL_SPOOLER) |
INFOCAD_TEST38.RPS_SETSPOOLER_STATUS |
ExportService.cs:358 |
Aggiornamento avanzamento (UPDATE GLOBAL_SPOOLER) |
INFOCAD_TEST38.RPS_SETSPOOLER_PROGRESS |
ExportService.cs:402 |
Cancellazione job per id (DELETE GLOBAL_SPOOLER) |
INFOCAD_TEST38.RPS_DELETESPOOLER_BYID |
ExportService.cs:61,440 |
| Registrazione job documenti (temp + MERGE) | INFOCAD_TEST38.DOC_INSERTSPOOLER_QUERY → RPS_SETSPOOLER_LASTQUERY |
Document_DAL.vb:3368 |
Tabelle lette (read)
INFOCAD_TEST38:GLOBAL_SPOOLER(lettura riga in coda / per id inRPS_GETSPOOLER_INFO).ASPNET_TEST38:ORA_ASPNET_USERS,ORA_ASPNET_APPLICATIONS(risoluzioneUSERIDdell'utente — daUSER_DEPENDENCIESdiRPS_SETSPOOLER_LASTQUERY/RPS_GETSPOOLER_INFO).- Percorso documenti:
DOCS_DOCUMENT_EXPORT,DOCS_IDDOCUMENT_TEMP_EXPORT(SELECT di export dentroDOC_INSERTSPOOLER_QUERY src:25-48).
Tabelle modificate (write)
INFOCAD_TEST38:GLOBAL_SPOOLER(RW — coda dei job di export):- INSERT/UPDATE via
MERGEinRPS_SETSPOOLER_LASTQUERY(registrazione job,STATUS = 0; colonneUSERID, EXPORTNAME, STATUS, EXPORTDATA, STARTDATE, EXPIREDATE, EXPORTKEYS, EXPORTTOTAL); - UPDATE
STATUS/FILENAMEviaRPS_SETSPOOLER_STATUS(ciclo di vita: 1 = in esecuzione, 2 = completato); - UPDATE
EXPORTPROGRESSviaRPS_SETSPOOLER_PROGRESS; - DELETE via
RPS_DELETESPOOLER_BYID(cleanup / rimozione job).
- INSERT/UPDATE via
DOCS_IDDOCUMENT_TEMP_EXPORT(RW — path documenti): DELETE per utente + INSERT id documenti inDOC_INSERTSPOOLER_QUERY(src:12-13,20-21), poi registrazione job viaRPS_SETSPOOLER_LASTQUERY.- Nota:
GLOBAL_SPOOLERha anche un TRIGGER (USER_OBJECTS→ TABLE + TRIGGER): l'ID_SPOOLERè verosimilmente assegnato da sequenza/trigger (non presente nel corpoRPS_SETSPOOLER_LASTQUERY; vedi Open questions).
Validazione
- Lato WCF:
ValidateToken(token: request.UserName)all'ingresso di ogni metodo di export (ApplicationService.svc.cs:150,158,172,186,200) — l'UserNameusato a valle è quello risolto dal token. - Lato DB:
RPS_SETSPOOLER_LASTQUERYrisolveUSERIDcon unaSELECT … INTO(src:17-23); se l'utente non esiste sollevaNO_DATA_FOUND(nessuna riga scritta).RPS_GETSPOOLER_INFOgestisce esplicitamenteNO_DATA_FOUNDrestituendo un cursore con-100(src:34-36). - Idempotenza registrazione: la chiave del
MERGE(USERID, STATUS = 0)garantisce una sola riga in coda per utente: una nuova richiesta aggiorna la riga pendente invece di duplicarla.
Side effects
- Creazione/aggiornamento della riga di spooler dell'utente (stato
0) conEXPIREDATE = SYSDATE + 1(scadenza a 24h → candidata aCleanExport/RPS_GETEXPIREDSPOOLERS+RPS_DELETESPOOLER_BYID). - Al completamento del job: file fisico prodotto in
_ctx.UserPath(Excel/ZIP/PDF) eFILENAMEregistrato inGLOBAL_SPOOLER(RPS_SETSPOOLER_STATUS,PSTATUS = 2). - Path documenti: svuotamento+ripopolamento di
DOCS_IDDOCUMENT_TEMP_EXPORTper l'utente. - Alla cancellazione (
DeleteSpooler_ByID): eliminazione del file su disco prima del DELETE della riga (ExportService.cs:412-440).
Percorsi alternativi / di errore
- Export griglia DataView (Excel):
ApplicationService.ExportData(:148) →DataViewExportController.StartExcelExport(user, fields, null)(:152) — la riga di spooler è già in stato0(registrata a monte); il job la legge viaRPS_GETSPOOLER_INFOe la porta a1→2. - Export documenti (Excel):
ExportDocument(:156) →DocumentController.InsertSpoolerExportData(:161) →Document_DAL.InsertSpoolerExportData→DOC_INSERTSPOOLER_QUERY(che popola la temp e chiamaRPS_SETSPOOLER_LASTQUERYcon la SELECT di export,src:50) →StartExcelExportForDocument(:165). - Export PDF/ZIP documenti:
ExportDocumentsData/ExportDocumentsDataZip(:184,198) →SetSpooler_LastQuery+DocumentExportController.StartExport/StartExportZip. - Errore utente inesistente:
SELECT … INTO USERIDinRPS_SETSPOOLER_LASTQUERY→NO_DATA_FOUNDnon gestito ⇒ eccezione propagata;SetSpooler_LastQueryrestituiscefalse/exception loggata (ExportService.cs:314-318) e il metodo WCF ritorna-1(ApplicationService.svc.cs:179). - Cleanup job scaduti:
CleanExport(ExportService.cs:32) →RPS_GETEXPIREDSPOOLERS+RPS_DELETESPOOLER_BYID(:41,61).
Diagramma di sequenza
sequenceDiagram
actor U as Utente
participant WCF as ApplicationService.svc (ExportImagesData)
participant CTRL as ExportServiceController (Remoting proxy)
participant SVC as ExportService (servizio Windows)
participant DV as DataViewService / DataViewExportReader
participant DB as Oracle INFOCAD_TEST38 (GLOBAL_SPOOLER)
U->>WCF: richiesta export (request)
WCF->>WCF: ValidateToken(request.UserName)
WCF->>CTRL: SetSpooler_LastQuery(user, name, sql)
CTRL->>SVC: (Remoting) SetSpooler_LastQuery(...)
SVC->>DB: RPS_SETSPOOLER_LASTQUERY (PUSERNAME, PNAME, PSQL)
alt nessuna riga in coda (STATUS=0)
DB->>DB: MERGE -> INSERT GLOBAL_SPOOLER (STATUS=0)
else riga in coda esistente
DB->>DB: MERGE -> UPDATE GLOBAL_SPOOLER (EXPORTNAME/EXPORTDATA...)
end
DB-->>SVC: OK
WCF->>CTRL: StartExport / StartExcelExport(user, ...)
CTRL->>DV: (Remoting) StartExport(...)
DV->>DB: RPS_GETSPOOLER_INFO -> ID_SPOOLER (STATUS=0)
DV->>DB: RPS_SETSPOOLER_STATUS(id, 1, '') (in esecuzione)
DV->>DB: RPS_GETSPOOLER_QUERY (estrazione dati)
DV->>DV: genera file (xlsx/zip/pdf) in UserPath
DV->>DB: RPS_SETSPOOLER_STATUS(id, 2, fileName) (completato)
DB-->>DV: OK
WCF-->>U: ID_SPOOLER (o -1 su errore)
Matrice di tracciabilità
| Layer | Artefatto | Evidenza (file:riga) |
|---|---|---|
| UI/Web (WCF) | ApplicationService.ExportImagesData → SetSpooler_LastQuery + StartExport |
ApplicationService.svc.cs:170,175,177 |
| UI/Web (WCF) | ExportData / ExportDocument / ExportDocumentsData(Zip) |
ApplicationService.svc.cs:148,156,184,198 |
| Controller (proxy) | ExportServiceController.SetSpooler_LastQuery (ctor Remoting) |
ExportServiceController.cs:17,53,55 |
| Interfaccia | IExportService.SetSpooler_LastQuery / SetSpooler_Status |
IExportService.cs:24,28 |
| Servizio (DAO) | ExportService.SetSpooler_LastQuery → RPS_SETSPOOLER_LASTQUERY |
ExportService.cs:298,312 |
| Servizio (DAO) | ExportService.SetSpooler_Status → RPS_SETSPOOLER_STATUS |
ExportService.cs:344,358 |
| Servizio (DAO) | SetSpooler_Progress / DeleteSpooler_ByID / CleanExport |
ExportService.cs:390,402,412,440,32,61 |
| Job | DataViewService.PrepareExcelJobForExecution → RPS_GETSPOOLER_INFO; StartExcelExport |
DataViewService.cs:17,37,78,85 |
| Job | DataViewExportReader.BaseGetData → SetSpooler_Status(id,1,'') + RPS_GETSPOOLER_QUERY |
DataViewExportReader.cs:48,78 |
| Job | DataViewDataReaderJob: new ExportService(); SetSpooler_Progress(100); SetSpooler_Status(id,2,file) |
DataViewDataReaderJob.cs:45,192,206 |
| Registrazione Remoting | RegisterWellKnownServiceType(DataViewService, "DataViewExportService.rem") |
Business/Start.vb:999 |
| Path documenti | Document_DAL.InsertSpoolerExportData → DOC_INSERTSPOOLER_QUERY |
Document_DAL.vb:3358,3368 |
| DB | RPS_SETSPOOLER_LASTQUERY (MERGE su GLOBAL_SPOOLER) |
USER_SOURCE RPS_SETSPOOLER_LASTQUERY src:17-23,25-34 |
| DB | RPS_SETSPOOLER_STATUS (UPDATE GLOBAL_SPOOLER) |
USER_SOURCE src:7-9 |
| DB | RPS_GETSPOOLER_INFO (SELECT GLOBAL_SPOOLER) |
USER_SOURCE src:8-32 |
| DB | DOC_INSERTSPOOLER_QUERY (temp + call RPS_SETSPOOLER_LASTQUERY) |
USER_SOURCE src:12-13,20-21,50 |
| DB (schema) | GLOBAL_SPOOLER colonne ID_SPOOLER(NUMBER), USERID(RAW), EXPORTNAME, STATUS, EXPORTDATA(CLOB), FILENAME, EXPIREDATE, EXPORTPROGRESS, EXPORTTOTAL |
USER_TAB_COLUMNS |
Reverse trace (dal DB/servizio ai chiamanti)
RPS_SETSPOOLER_LASTQUERY(dipendenzeUSER_DEPENDENCIES:GLOBAL_SPOOLER,ASPNET_TEST38.ORA_ASPNET_USERS/APPLICATIONS,HELPERS,MYINTTABLE) è la procedura di registrazione job. È raggiunta da: (a)ExportService.SetSpooler_LastQuery(ExportService.cs:312), a sua volta invocata daApplicationService.ExportImagesData/ExportDocumentsData/ExportDocumentsDataZip(ApplicationService.svc.cs:175,189,203); (b) internamente daDOC_INSERTSPOOLER_QUERY src:50(path documenti Excel, viaDocument_DAL.InsertSpoolerExportData).RPS_SETSPOOLER_STATUS(dipende solo daGLOBAL_SPOOLER) è invocata daExportService.SetSpooler_Status(ExportService.cs:358), chiamata da tutti i reader/job di export all'avvio (…, 1, "") e al termine (…, 2, fileName): DataView (DataViewExportReader.cs:48,DataViewDataReaderJob.cs:206), Immagini (ImagesDataReaderJob.cs:225), Maintenance (MaintenanceDataReaderJob.cs:158), Documenti (DocumentsPDFJob.cs:190,DocumentsZipJob.cs:238).- Forward e reverse concordano: il metodo WCF di export registra il job con
RPS_SETSPOOLER_LASTQUERY(INSERTGLOBAL_SPOOLER,STATUS=0) e i job aggiornano la stessa riga conRPS_SETSPOOLER_STATUS→ NO CONFLICTING.
Regole correlate (related rules)
- Modello a spooler asincrono: ogni export è persistito come riga di
GLOBAL_SPOOLERcon macchina a statiSTATUS:0in coda →1in esecuzione →2completato (RPS_SETSPOOLER_STATUS src:7-9; costanti nei reader). - Una sola richiesta pendente per utente: chiave
MERGE (USERID, STATUS=0)(src:25-28). - Scadenza a 24h:
EXPIREDATE = SYSDATE + 1(src:32), abbinata al cleanupRPS_GETEXPIREDSPOOLERSRPS_DELETESPOOLER_BYID.
- Multi-tenant/identità:
USERIDrisolto daASPNET_TEST38filtrando anche perLOWER(USER)(schema applicativo corrente) → isolamento per applicazione/tenant (src:22). - .NET Remoting
SingleCallcome trasporto client→servizio (non WCF):Business/Start.vb:999+.
Evidenza (file:line)
Punti chiave (codice):
ApplicationService.svc.cs:148,150,156,158,161,165,170,172,173,174,175,177,184,186,189,191,198,200,203;
ExportServiceController.cs:17,53,55; IExportService.cs:24,28;
ExportService.cs:32,41,61,70,298,312,344,358,390,402,412,440;
DataViewService.cs:17,34,37,78,85,92,107,110,134,147;
DataViewExportReader.cs:48,78; DataViewDataReaderJob.cs:31,45,192,206;
Business/Start.vb:999; Document_DAL.vb:3358,3368.
Punti chiave (DB, INFOCAD_TEST38, letti in sola lettura via USER_SOURCE/USER_DEPENDENCIES/USER_TAB_COLUMNS/USER_OBJECTS):
RPS_SETSPOOLER_LASTQUERY firma src:1-5; risoluzione USERID src:17-23; conteggio chiavi src:12-15;
MERGE su GLOBAL_SPOOLER INSERT/UPDATE src:25-34.
RPS_SETSPOOLER_STATUS UPDATE GLOBAL_SPOOLER src:7-9.
RPS_GETSPOOLER_INFO SELECT (per id / per utente+STATUS=0) src:8-32, NO_DATA_FOUND src:34-36.
DOC_INSERTSPOOLER_QUERY DELETE/INSERT temp src:12-13,20-21, call RPS_SETSPOOLER_LASTQUERY src:50.
GLOBAL_SPOOLER è TABLE (+ TRIGGER) con colonne ID_SPOOLER NUMBER (NOT NULL), USERID RAW,
EXPORTNAME/FILENAME VARCHAR2, STATUS/EXPORTPROGRESS/EXPORTTOTAL/ISPUBLIC NUMBER,
EXPORTDATA/EXPORTKEYS CLOB, STARTDATE/EXPIREDATE DATE (USER_TAB_COLUMNS).
Dipendenze RPS_SETSPOOLER_LASTQUERY → GLOBAL_SPOOLER, ASPNET_TEST38.ORA_ASPNET_USERS/APPLICATIONS,
HELPERS (PACKAGE), MYINTTABLE (TYPE) (USER_DEPENDENCIES).
Confidence
VERIFIED. La catena WCF → controller (Remoting) → servizio ExportService → DAL
ExecuteNonQueryStoredProcedure → RPS_SETSPOOLER_LASTQUERY è confermata sul codice; l'effetto di
scrittura (INSERT/UPDATE su GLOBAL_SPOOLER) e l'aggiornamento di stato (RPS_SETSPOOLER_STATUS) sono
confermati sul sorgente Oracle (USER_SOURCE) e sul catalogo (USER_TAB_COLUMNS,
USER_DEPENDENCIES, USER_OBJECTS). ≥2 tipi di evidenza (codice C#/VB.NET + sorgente/catalogo DB).
Open questions
- Assegnazione di
ID_SPOOLER:GLOBAL_SPOOLERha un TRIGGER (daUSER_OBJECTS) verosimilmente incaricato di popolareID_SPOOLERda sequenza sull'INSERT; il corpo del trigger non è stato ispezionato. - Dove viene registrata la query SQL reale per l'export della griglia DataView (nei metodi WCF
ExportImagesData/ExportDocumentsDatail parametroPSQLèstring.Empty): esiste con ogni probabilità un'impostazione a monte dell'"ultima query" del DataView che valorizzaEXPORTDATA; non individuato il chiamante che passa il SQL non vuoto (fuori dominio ExportService). - Semantica esatta dei valori
STATUSoltre a0/1/2(es. eventuali stati di errore) non normata nel codice ispezionato. RPS_GETSPOOLER_QUERY(estrazione dati da esportare) non ispezionata in dettaglio sul sorgente DB (letta solo come READ nel reader).