RequestCenter.Transaction
Unità di lavoro (unit-of-work) del layer BL di RequestCenter: incapsula il ciclo di vita della connessione Oracle condivisa
cm(GlobalDataManager) e la transazione che vi si appoggia, esponendoOpenConnection/Begin/Commit/Rollback/CloseConnection. Classificazione complessiva: VERIFIED (sorgenteTransaction.vb+ implementazione DAL + uso reale inmakeTicket.ascx.vb).
Scopo
Transaction è una facade sottile che il codice di presentazione (code-behind) usa per delimitare una scrittura atomica su Oracle: apre la connessione, avvia la transazione, e dopo il lavoro del BL/DAL decide Commit o Rollback, chiudendo infine la connessione. Non contiene logica di dominio né SQL: delega interamente all'implementazione DAL risolta a runtime, che a sua volta pilota il GlobalDataManager condiviso della richiesta. Classificazione: VERIFIED (Transaction.vb:3-30; TransactionDAL.vb:12-43).
Namespace e progetto
- Tipo:
Transaction(globale rispetto alla radiceDescor.RequestCenter, dichiarato senza bloccoNamespaceinTransaction.vb; usato comeRequestCenter.Transactiondal web). SUPPORTED (Transaction.vb:3; uso qualificato inmakeTicket.ascx.vb:88). - Progetto:
RequestCenter(RequestCenter.vbproj, VB.NET net48,RootNamespace Descor.RequestCenter), fileTransaction/Transaction.vb. - Interfaccia di contratto:
Descor.RequestCenter.Interfaces.Transaction.ITransactionDAL(Interfaces/TransactionInterfaces.vb:3). - Implementazione DAL:
TransactionDAL/MobileTransactionDALnel progettoRequestCenter.DAL.OracleODP(TransactionDAL.vb:12,45).
Nello stesso file convive MobileTransaction, gemello identico che si differenzia solo per la factory DAL usata (GetMobileTransactionDAL invece di GetTransactionDAL). VERIFIED (Transaction.vb:32-59).
Responsabilità
- Aprire e chiudere la connessione Oracle di richiesta (
OpenConnection/CloseConnection). - Avviare, confermare o annullare la transazione (
Begin/Commit/Rollback). - Fare da punto di ingresso stabile per il code-behind, disaccoppiandolo dal DAL concreto (risolto per reflection dalla
DALFactory).
Non è responsabile di: aprire connessioni per singola query (lo fa il DAL di dominio tramite lo stesso cm), scegliere l'IsolationLevel (delegato a GlobalDataManager), o eseguire SQL.
Perché esiste
UNKNOWN — non è documentata nel sorgente una motivazione storica/di business esplicita. Il ruolo tecnico (facade unit-of-work sul GlobalDataManager condiviso) è invece supportato dal codice; vedi Scopo e Ciclo di vita.
Contratto pubblico
Cinque Public Sub senza parametri né valore di ritorno, tutti a delega diretta verso ITransactionDAL (VERIFIED, Transaction.vb:5-28):
| Membro | Delega a | Effetto sul GlobalDataManager |
|---|---|---|
OpenConnection() |
ITransactionDAL.OpenConnection |
cm.Open() — apre se Connection.State = Closed |
Begin() |
ITransactionDAL.Begin |
cm.BeginTransaction() se Not cm.InTransaction |
Commit() |
ITransactionDAL.Commit |
cm.CommitTransaction() se cm.InTransaction |
Rollback() |
ITransactionDAL.Rollback |
cm.RollbackTransaction() se cm.InTransaction |
CloseConnection() |
ITransactionDAL.CloseConnection |
cm.Close() — chiude la connessione |
ITransactionDAL eredita IBaseDAL e dichiara esattamente questi cinque Sub (VERIFIED, TransactionInterfaces.vb:3-11).
Implementazioni o classi derivate
TransactionDAL(InheritsBaseDAL, ImplementsITransactionDAL) — implementazione Oracle standard. VERIFIED (TransactionDAL.vb:12-43).MobileTransactionDAL— implementazione identica riga per riga, distinta come tipo separato per il canale "mobile". VERIFIED (TransactionDAL.vb:45-76).MobileTransaction(BL) — facade gemella diTransactionche instrada versoMobileTransactionDAL. VERIFIED (Transaction.vb:32-59).
Dipendenze
DALFactory.GetTransactionDAL()/GetMobileTransactionDAL()— risolvono l'implementazione per reflection: caricano l'assembly DAL (Configuration.Settings.DALTypeName, con suffissoXNETsotto net8) e istanziano il tipo…TransactionDALviaActivator.CreateInstance, memorizzandolo in un dizionario statico_instances. VERIFIED (DALFactory.vb:36-41,159-165).Configuration.Settings.GetConnectionManager()— fornisce ilGlobalDataManager(cm) condiviso, conservato inHttpContext.Current.Items("RCCONNECTIONMANAGER")(uno per richiesta HTTP; fallback WCFOperationContext). VERIFIED (Settings.vb:242-296).GlobalDataManager(progettoDataManager) — motore effettivo di connessione/transazione. Vedi class-GlobalDataManager.md.- Driver Oracle:
Oracle.DataAccess(unmanaged) sotto net48;Oracle.ManagedDataAccesssotto net8 (guardia#If NET5_0_OR_GREATER). VERIFIED (TransactionDAL.vb:3-10).
Ciclo di vita
La facade è stateless: Dim dal As ITransactionDAL = DALFactory.GetTransactionDAL viene richiamata a ogni metodo (VERIFIED, Transaction.vb:6,11,16,21,26). Lo stato reale (connessione + transazione) vive nel GlobalDataManager di richiesta, non nell'istanza Transaction.
Ciclo tipico osservato nel flusso di creazione ticket (makeTicket.ascx.vb, VERIFIED):
Dim objTransaction As New RequestCenter.Transaction—:88.objTransaction.OpenConnection()—:111→cm.Open().objTransaction.Begin()—:112→cm.BeginTransaction().- Lavoro BL/DAL nella stessa richiesta (
Request.Create,SetWorkflowInterface, …) sullo stessocm. objTransaction.Commit()—:216→cm.CommitTransaction().- In caso di eccezione:
objTransaction.Rollback()nel bloccoCatch—:240. objTransaction.CloseConnection()nel bloccoFinally—:254→cm.Close().
L'istanza DAL sottostante, invece, non è per-richiesta: DALFactory la memorizza in cache statica e la riusa per l'intero processo (vedi Thread safety).
Stato interno
Transaction/MobileTransaction: nessun campo. VERIFIED (Transaction.vb:3-59).TransactionDAL/MobileTransactionDAL: unico campoPrivate _cm As GlobalDataManager = Nothing, inizializzato pigramente al primo metodo invocato (If _cm Is Nothing Then _cm = Configuration.Settings.GetConnectionManager) e mai reimpostato. VERIFIED (TransactionDAL.vb:16,19,24,29,34,39).
Metodi principali
Tutti i metodi sono a corpo unico e delegano al DAL; non richiedono un method-block dettagliato. Il comportamento significativo è nel DAL (TransactionDAL.vb):
Begin→ apre la transazione solo se non già attiva (If Not _cm.InTransaction Then _cm.BeginTransaction());BeginTransactiona sua volta apre la connessione se chiusa. VERIFIED (TransactionDAL.vb:18-21;GlobalDataManager.vb:155-161).Commit/Rollback→ agiscono solo se_cm.InTransaction, poiDisposedella transazione e azzeramento del riferimento. VERIFIED (TransactionDAL.vb:23-31;GlobalDataManager.vb:171-189).CloseConnection→_cm.Close(); l'overload di default diGlobalDataManager.Close()esegueClose(PendingTransactionAction.Rollback), quindi annulla qualunque transazione ancora pendente prima di chiudere la connessione. VERIFIED (TransactionDAL.vb:33-36;GlobalDataManager.vb:133-149).
Collaborazioni
- BL e DAL condividono lo stesso
cm:Transactione i DAL di dominio (es.RequestDAL) ottengono entrambi ilGlobalDataManagerdaConfiguration.Settings.GetConnectionManager, che ritorna l'oggetto unico diHttpContext.Current.Items("RCCONNECTIONMANAGER"). Perciò la transazione aperta daTransaction.Begin()copre le scritture eseguite dai DAL nella medesima richiesta HTTP, senza passaggio esplicito di connessione. INFERRED (condivisione via chiaveRCCONNECTIONMANAGER,Settings.vb:245,285-295; il passaggio delcmai singoli DAL è documentato in class-RequestDAL.md). - Code-behind chiamante:
makeTicket.ascx.vb(Descor.RequestCenterWeb.makeTicket). VERIFIED (makeTicket.ascx.vb:88-255).
Accesso al database
Nessun accesso diretto. Transaction non nomina package, stored procedure o tabelle: apre/chiude connessione e transazione. Le scritture della richiesta (package GESTREQUEST/GESTREQUEST_T2 ecc.) sono eseguite dai DAL di dominio all'interno della finestra transazionale. Vedi la matrice DB in REQUESTCENTER_TEST38 e la crud-matrix.
Transazioni
La gestione transazionale è interamente delegata a GlobalDataManager:
Beginusa l'overload senzaIsolationLevel(Connection.BeginTransaction()), quindi vale il livello di isolamento di default del provider/DB Oracle;Transactionnon lo imposta. Esiste inGlobalDataManagerun overloadBeginTransaction(isolationLevel As IsolationLevel), ma la facade non lo invoca. VERIFIED (GlobalDataManager.vb:155-169;TransactionDAL.vb:20).- Idempotenza:
Begin/Commit/Rollbacksono protetti dal guardianoInTransaction, quindi chiamate ridondanti sono no-op (non sollevano eccezione). VERIFIED (TransactionDAL.vb:20,25,30).
Autorizzazione
Nessun controllo di autorizzazione in questa classe. Il gating dell'operazione (contesto utente, PreInit di pagina) è a monte, nel web tier.
Side effect
- Apre/chiude una connessione Oracle fisica sul
GlobalDataManagerdi richiesta. VERIFIED (GlobalDataManager.vb:104-149). Open()conDbSessionParamsvalorizzati esegue la stored procedureSET_CONTEXT_VALUEper impostare il contesto di sessione DB (utente/sorgente). SUPPORTED (GlobalDataManager.vb:113-117).Commit/RollbackfannoDisposedell'oggetto transazione. VERIFIED (GlobalDataManager.vb:176,186).
Gestione degli errori
- La facade non intercetta eccezioni: eventuali errori del DAL/
GlobalDataManagerrisalgono al chiamante. VERIFIED (Transaction.vb:5-28). - La disciplina di rollback è nel chiamante: nel flusso ticket il
Rollbackè nelCatch(makeTicket.ascx.vb:240) eCloseConnectionnelFinally(:254). - Rete di sicurezza: anche se il chiamante omettesse il
Rollback,CloseConnection→cm.Close()annulla la transazione pendente di default. VERIFIED (GlobalDataManager.vb:133-149). - Se il
GlobalDataManagerè già_disposed, i suoi metodi sollevanoObjectDisposedException. VERIFIED (GlobalDataManager.vb:75,107,138,156,172,182).
Thread safety
- L'istanza
Transaction/MobileTransactionè stateless: non condivide stato tra thread. - Il
GlobalDataManagersottostante è request-scoped (HttpContext.Current.Items), quindi non condiviso tra richieste HTTP concorrenti. INFERRED (Settings.vb:244-245). - Concern (INFERRED): l'istanza
TransactionDALè un singleton di processo (cache staticaDALFactory._instances,DALFactory.vb:36-41) e il suo campo_cmviene valorizzato una sola volta al primo utilizzo (If _cm Is Nothing …) e mai rinnovato. Sotto più richieste concorrenti,_cmresta legato alGlobalDataManagerdella prima richiesta invece che a quello della richiesta corrente ottenibile daGetConnectionManager. Non è stato osservato un meccanismo che azzeri_cmper richiesta; l'effetto è un potenziale disallineamento tra la connessione usata dalTransaction/DAL di dominio e quella attesa. Da verificare con esecuzione reale (non possibile su questo host). Vedi Debito tecnico.
Considerazioni sulle prestazioni
Il riuso della connessione di richiesta (una Open/Close per unità di lavoro anziché per query) riduce l'apertura ripetuta di connessioni Oracle. Nessun altro impatto rilevabile staticamente.
Esempio di utilizzo
Convenzione reale dal flusso di creazione ticket (verificata staticamente, non eseguita su questo host):
Dim objTransaction As New RequestCenter.Transaction
Try
objTransaction.OpenConnection() ' :111
objTransaction.Begin() ' :112
' ... scritture BL/DAL sullo stesso cm ...
objTransaction.Commit() ' :216
Catch ex As Exception
objTransaction.Rollback() ' :240
' logging / refresh cache ...
Finally
objTransaction.CloseConnection() ' :254
End Try
Test correlati
Nessun test automatico nel repository (0 test in tutta la codebase). Copertura non misurata.
Flussi correlati
- FLOW-REQ-001 — Creazione ticket (delimitazione transazionale:
makeTicket.ascx.vb:88,111,112,216,254).
Regole di business correlate
Limitazioni
IsolationLevelnon selezionabile tramite questa facade (usa il default del provider).- Nessun
TransactionScope/enlistment distribuito: la transazione è locale alla singolaOracleConnectiondelGlobalDataManager.
Debito tecnico
- Duplicazione integrale tra
Transaction/MobileTransactione traTransactionDAL/MobileTransactionDAL(corpi identici, unica differenza la factory). VERIFIED (Transaction.vb:3-59;TransactionDAL.vb:12-76). - Campo
_cmdel DAL singleton mai rinnovato (vedi Thread safety). INFERRED.
Evidenze
InfocadWeb/WebMachine/RequestCenter/Transaction/Transaction.vb:3(classTransaction),:5-28(metodi delega),:32-59(MobileTransaction).InfocadWeb/WebMachine/RequestCenter/Interfaces/TransactionInterfaces.vb:1-13(namespaceInterfaces.Transaction,ITransactionDALa :3,Inherits IBaseDAL).InfocadWeb/WebMachine/RequestCenter.DAL.OracleODP/TransactionDAL.vb:12-43(TransactionDAL),:45-76(MobileTransactionDAL); campo_cm:16,49; guardie driver :3-10.InfocadWeb/WebMachine/RequestCenter/DALFactory.vb:36-41(GetInstanceOfType+ cache_instances),:159-165(GetTransactionDAL/GetMobileTransactionDAL).InfocadWeb/WebMachine/RequestCenter/Configuration/Settings.vb:242-296(GetConnectionManager, chiaveRCCONNECTIONMANAGER).InfocadWeb/WebMachine/DataManager/GlobalDataManager.vb:81-87(InTransaction),:104-149(Open/Close),:155-189(BeginTransaction/overloadIsolationLevel/CommitTransaction/RollbackTransaction).InfocadWeb/WebMachine/CASSANDRA/RequestCenterWeb/UserControls/FlowActions/makeTicket.ascx.vb:82(btnPost_Click),:88(New RequestCenter.Transaction),:111OpenConnection,:112Begin,:216Commit,:240Rollback,:252-255Finally/CloseConnection.- Oggetti DB: connessione Oracle via
GlobalDataManager(nessuna stored procedure invocata direttamente daTransaction;SET_CONTEXT_VALUEinvocata daGlobalDataManager.Openquando presentiDbSessionParams).