Utilizzo delle operazioni di database sincrone

Adobe AIR 1.0 e versioni successive

Il codice effettivo utilizzato per eseguire le operazioni e rispondervi nella modalità sincrona non è molto diverso da quello utilizzato nella modalità di esecuzione asincrona. Le differenze fondamentali fra i due approcci riguardano due aspetti: il primo è l'esecuzione di un'operazione che dipende da un'altra operazione (come ad esempio le righe risultanti da SELECT o la chiave primaria della riga aggiunta dall'istruzione INSERT). Il secondo aspetto in cui vi è una differenza è la gestione degli errori.

Scrittura del codice per le operazioni sincrone

La differenza fondamentale tra l'esecuzione sincrona e quella asincrona è che in modalità sincrona il codice viene creato come serie singola di passi successivi. Nel codice asincrono, invece, si registrano listener degli eventi e spesso si dividono le operazioni fra vari metodi listener. Quando un database è connesso in modalità di esecuzione sincrona è possibile eseguire su di esso una serie di operazioni una dopo l'altra all'interno di un singolo blocco di codice. Questa tecnica viene dimostrata nell'esempio seguente:

var conn:SQLConnection = new SQLConnection(); 
     
// The database file is in the application storage directory 
var folder:File = File.applicationStorageDirectory; 
var dbFile:File = folder.resolvePath("DBSample.db"); 
     
// open the database 
conn.open(dbFile, OpenMode.UPDATE); 
     
// start a transaction 
conn.begin(); 
     
// add the customer record to the database 
var insertCustomer:SQLStatement = new SQLStatement(); 
insertCustomer.sqlConnection = conn; 
insertCustomer.text = 
    "INSERT INTO customers (firstName, lastName) " +  
    "VALUES ('Bob', 'Jones')"; 
insertCustomer.execute(); 
     
var customerId:Number = insertCustomer.getResult().lastInsertRowID; 
     
// add a related phone number record for the customer 
var insertPhoneNumber:SQLStatement = new SQLStatement(); 
insertPhoneNumber.sqlConnection = conn; 
insertPhoneNumber.text =  
    "INSERT INTO customerPhoneNumbers (customerId, number) " +  
    "VALUES (:customerId, '800-555-1234')"; 
insertPhoneNumber.parameters[":customerId"] = customerId; 
insertPhoneNumber.execute(); 
     
// commit the transaction 
conn.commit(); 

Come si vede, si chiamano gli stessi metodi per eseguire le operazioni del database, sia che si stia utilizzando la modalità sincrona che quella asincrona. Le differenze chiave fra i due approcci risiedono nell'esecuzione di un'operazione che dipende da un'altra operazione e nella gestione degli errori.

Esecuzione di un'operazione che dipende da un'altra

Quando si usa la modalità di esecuzione sincrona non è necessario scrivere codice che rilevi gli eventi per determinare quando una certa operazione viene completata. È sufficiente invece partire dal presupposto che, se un'operazione di una riga del codice viene completata correttamente, l'esecuzione prosegue con la riga successiva del codice. Di conseguenza, per eseguire un'operazione che dipende dalla riuscita di un'altra operazione, è sufficiente scrivere il codice dipendente immediatamente dopo l'operazione da cui dipende. Ad esempio, per comandare tramite il codice a un'applicazione di dare inizio a una transazione, eseguire l'istruzione INSERT, recuperare la chiave primaria della riga inserita, inserire tale chiave in un'altra riga di una tabella diversa e infine eseguire il commit della transazione, è possibile scrivere tutto il codice sotto forma di una serie di istruzioni, come dimostrato nell'esempio seguente.

var conn:SQLConnection = new SQLConnection(); 
     
// The database file is in the application storage directory 
var folder:File = File.applicationStorageDirectory; 
var dbFile:File = folder.resolvePath("DBSample.db"); 
     
// open the database 
conn.open(dbFile, SQLMode.UPDATE); 
     
// start a transaction 
conn.begin(); 
     
// add the customer record to the database 
var insertCustomer:SQLStatement = new SQLStatement(); 
insertCustomer.sqlConnection = conn; 
insertCustomer.text = 
    "INSERT INTO customers (firstName, lastName) " +  
    "VALUES ('Bob', 'Jones')"; 
insertCustomer.execute(); 
     
var customerId:Number = insertCustomer.getResult().lastInsertRowID; 
     
// add a related phone number record for the customer 
var insertPhoneNumber:SQLStatement = new SQLStatement(); 
insertPhoneNumber.sqlConnection = conn; 
insertPhoneNumber.text =  
    "INSERT INTO customerPhoneNumbers (customerId, number) " +  
    "VALUES (:customerId, '800-555-1234')"; 
insertPhoneNumber.parameters[":customerId"] = customerId; 
insertPhoneNumber.execute(); 
     
// commit the transaction 
conn.commit(); 

Gestione degli errori nell'esecuzione sincrona

Nella modalità di esecuzione sincrona non si rilevano gli eventi di errore per determinare se un'operazione non è riuscita. Si circondano invece le eventuali parti del codice che potrebbero dare luogo a errori con un set di blocchi try..catch..finally. Con il blocco try si circonda il codice che può dare luogo a errori. Scrivete le azioni da eseguire in risposta a ciascun tipo di errore entro blocchi catch separati. Ponete l'eventuale codice che desiderate venga sempre eseguito indipendentemente dalla riuscita o meno (ad esempio la chiusura della connessione a un database non più necessario) nel blocco finally. L'esempio che segue illustra l'uso dei blocchi try..catch..finally per la gestione degli errori. Questo esempio espande il precedente aggiungendo il codice di gestione degli errori.

var conn:SQLConnection = new SQLConnection(); 
     
// The database file is in the application storage directory 
var folder:File = File.applicationStorageDirectory; 
var dbFile:File = folder.resolvePath("DBSample.db"); 
     
// open the database 
conn.open(dbFile, SQLMode.UPDATE); 
     
// start a transaction 
conn.begin(); 
     
try 
{ 
    // add the customer record to the database 
    var insertCustomer:SQLStatement = new SQLStatement(); 
    insertCustomer.sqlConnection = conn; 
    insertCustomer.text = 
        "INSERT INTO customers (firstName, lastName)" +  
        "VALUES ('Bob', 'Jones')"; 
     
    insertCustomer.execute(); 
     
    var customerId:Number = insertCustomer.getResult().lastInsertRowID; 
     
    // add a related phone number record for the customer 
    var insertPhoneNumber:SQLStatement = new SQLStatement(); 
    insertPhoneNumber.sqlConnection = conn; 
    insertPhoneNumber.text =  
        "INSERT INTO customerPhoneNumbers (customerId, number)" +  
        "VALUES (:customerId, '800-555-1234')"; 
    insertPhoneNumber.parameters[":customerId"] = customerId; 
     
    insertPhoneNumber.execute(); 
     
    // if we've gotten to this point without errors, commit the transaction 
    conn.commit(); 
} 
catch (error:SQLError) 
{ 
    // rollback the transaction 
    conn.rollback(); 
}