2013-05-14 9 views
10

ExtJS 4.1.0ExtJS e Complesso operazioni di salvataggio

Aggiornamento 6/6/13:

ho postato questa stessa domanda sul forum di Sencha in cui non vi sia stata molta azione. Il post è più o meno lo stesso, ma ho pensato di aggiungerlo qui solo per riferimento. Sono ancora ansioso di sentire l'input di altri membri della comunità su quello che deve essere uno scenario molto comune in un'applicazione ExtJS! http://www.sencha.com/forum/showthread.php?265358-Complex-Model-Save-Decoupling-Data-and-Updating-Related-Stores

aggiornamento 7/16/13 (Conclusione?)

Il post Sencha ha ottenuto molto poco discussione. Ho deciso di mettere la maggior parte del carico di operazioni di salvataggio complesse sul mio server applicazioni e aggiornare pigramente gli archivi dei clienti dove necessario. In questo modo posso utilizzare il mio wrapper del database per comprendere tutte le transazioni associate a un salvataggio di oggetto dominio complesso per garantire l'atomicità. Se il salvataggio di un nuovo Order consiste nel salvare i metadati dell'ordine, dieci nuove istanze di OrderContents e potenzialmente altre informazioni (indirizzi residenti in altre tabelle, un nuovo cliente definito al momento della creazione dell'ordine, ecc.) Preferirei inviare il carico utile a il server delle applicazioni, piuttosto che creare una volgare rete di callback nel codice dell'applicazione lato client. I dati associati su base One-to-One (come ad esempio Order hasOne Address) vengono aggiornati nella richiamata success dell'operazione Order.save(). Dati più complessi, come il contenuto di Order, vengono gestiti pigramente chiamando semplicemente contentStore.sync(). sento che questo è il mezzo per garantire atomicità senza un numero enorme di clienti-callback

originale pubblicare contenuti

Data la funzionalità deludente complessiva di salvare modelli di associazione-pesante, ho tutti, ma piantato in asso associazioni di modelli nella mia applicazione e si basano sul recupero dei dati associati personalmente. Questo è tutto a posto, ma sfortunatamente non risolve il problema del salvataggio effettivo dei dati e dell'aggiornamento degli archivi ExtJS per riflettere le modifiche sul server.

Prendiamo ad esempio il salvataggio di un oggetto Order, che è composto da metadati e OrderContents, cioè le parti nell'ordine. I metadati finiscono in una tabella Order_Data nel database, mentre i contenuti finiscono tutti in una tabella Order_Contents in cui ogni riga è collegata all'ordine genitore tramite una colonna order_id.

Sul client, recuperare i contenuti per un ordine è abbastanza semplice da fare senza bisogno di associazioni: var contents = this.getContentsStore().query('order_id', 10).getRange(). Tuttavia, un difetto importante è che il numero è disponibile nei record di contenuto disponibili nello Store OrderContents ExtJS, che si applicherebbe se si utilizzassero associazioni NON restituite dal server di dati con l'oggetto "principale".

Durante il salvataggio di un ordine, invio una singola richiesta che contiene i metadati dell'ordine (ad es. Data, numero dell'ordine, informazioni sul fornitore, ecc.) Nonché una serie di contenuti. Questi pezzi di dati vengono raccolti e salvati nelle tabelle appropriate. Questo ha senso per me e funziona bene.

Tutto va bene finché non viene restituito il record salvato/aggiornato dal server delle applicazioni.Dal momento che la richiesta viene interrotta chiamando uno OrderObject.save(), non c'è nulla che dice al negozio OrderContents che sono disponibili nuovi record. Questo sarebbe gestito automaticamente se dovessi invece aggiungere record allo store e chiamare .sync(), ma ritengo che questo complichi il processo di salvataggio e vorrei piuttosto gestire questo disaccoppiamento sul server delle applicazioni per non parlare, salvare un'intera richiesta è abbastanza bello pure.

C'è un modo migliore per risolvere questo? La mia soluzione attuale è la seguente ...

var orderContentsStore = this.getOrderContentsStore(); 
MyOrderObject.save({ 
    success: function(rec, op){ 
     // New Content Records need to be added to the contents store! 
     orderContentsStore.add(rec.get('contents')); // Array of OrderContent Records 
     orderContentsStore.commitChanges(); // This is very important 
    } 
}); 

Chiamando commitChanges() i record aggiunti al negozio sono considerati puliti (non-fantasma, non sporco) e, quindi, non sono più restituito dal metodo del negozio getModifiedRecords() ; giustamente, in quanto i record non devono essere trasmessi al server delle applicazioni in caso di store.sync().

Questo approccio sembra solo un pò sciatto/hacky a me, ma non ho capito una soluzione migliore ...

Qualsiasi ingresso/pensieri sono molto apprezzate!

+1

Purtroppo questo è l'unico modo per farlo. In alternativa, potresti scrivere il tuo "writer" sul proxy del negozio e gestire i diversi modelli lì, ma anche questo sarebbe disordinato. – Mike

+0

Grazie per aver confermato le mie convinzioni, @ Mike. Ho intenzione di scrivere un post sul blog un giorno e risponderò a questa domanda con le informazioni di detto post. Ho preso in considerazione l'implementazione di qualche estensione pazzesca per il Data Writer, ma per quello che avrebbe ottenuto (salvando un store.load() qua e là), ritengo che la complessità e il tempo necessari per implementare solo non varrà la pena. –

risposta

3

aggiornamento 8/26/13 ho trovato che i dati associati è infatti gestito da Ext nella richiamata creare/aggiornamento sulla delega del modello, ma trovare che i dati non è stato facile ... Vedere il mio post qui: ExtJS 4.1 - Returning Associated Data in Model.Save() Response

Beh, sono passati un paio di mesi da questa domanda e ho la sensazione che non ci sia una soluzione magicamente eccezionale a questo problema.

La mia soluzione è la seguente ...

Quando si salva un modello complesso (ad esempio, un modello che, o che hanno un paio di hasMany associazioni), risparmio il modello di 'genitore', che comprende tutti i dati associati (come una proprietà/campo sul modello!) e quindi aggiungere i dati associati (salvati) nel callback afterSave/afterUpdate.

Prendiamo ad esempio il mio PurchaseOrder modello che hasManyItems e hasOneAddress. Prendi nota che i dati associati sono inclusi nelle proprietà del modello, in quanto non verranno passati al server se esiste esclusivamente nell'archivio di associazione del modello.

console.log(PurchaseOrder.getData()); 
--- 
id: 0 
order_num: "PO12345" 
order_total: 100.95 
customer_id: 1 
order_address: Object 
    id: 0 
    ship_address_1: "123 Awesome Street" 
    ship_address_2: "Suite B" 
    ship_city: "Gnarlyville" 
    ship_state: "Vermont" 
    ship_zip: "05401" 
    ...etc... 
contents: Array[2] 
    0: Object 
     id: 0 
     sku: "BR10831" 
     name: "Super Cool Shiny Thing" 
     quantity: 5 
     sold_price: 84.23 
    1: Object 
     id: 0 
     sku: "BR10311" 
     name: "Moderately Fun Paddle Ball" 
     quantity: 1 
     sold_price: 1.39 

ho Models stabilito per PurchaseOrder.Content e PurchaseOrder.Address, eppure i dati nella PurchaseOrder non è un esempio di questi modelli, piuttosto solo i dati. Di nuovo, questo è per assicurarsi che sia passato correttamente al server delle applicazioni.

Una volta che ho un oggetto come descritto sopra, mando via al mio server applicativo tramite .save() come segue:

PurchaseOrder.save({ 
    scope: me, 
    success: me.afterOrderSave, 
    failure: function(rec,op){ 
     console.error('Error saving Purchase Order', op); 
    } 
}); 

afterOrderSave: function(record, operation){ 
    var me = this; 
    switch(operation.action){ 
     case 'create': 
      /** 
       * Add the records to the appropriate stores. 
       * Since these records (from the server) have an id, 
       * they will not be marked as dirty nor as phantoms 
       */ 
      var savedRecord = operation.getResultSet().records[0]; // has associated! 
      me.getOrderStore().add(savedRecord); 
      me.getOrderContentStore().add(savedRecord.getContents()); //association! 
      me.getOrderAddressStore().add(savedRecord.getAddress()); // association! 
      break; 

     case 'update': 
      // Locate and update records with response from server 
      break; 
    } 
} 

My application server riceve il PurchaseOrder e gestisce il salvataggio dei dati di conseguenza. Non entrerò nei dettagli grossolani in quanto questo processo dipende in gran parte dalla vostra implementazione. Il mio framework applicativo è liberamente basato su Zend 1.11 (principalmente facendo leva su Zend_Db).

sento che questo è l'approccio migliore per i seguenti motivi:

  • No stringa disordinato di vari modelli.save() callback sul client
  • Solo una richiesta, che è molto facile da gestire
  • Atomicity è facilmente gestito sul server applicazioni
  • viaggi
  • Meno giro = meno potenziali punti di guasto di cui preoccuparsi
  • Se ti senti davvero pigro, il metodo success della richiamata può semplicemente memorizzare reload.

Lascerò questa risposta per un po 'per incoraggiare la discussione.

Grazie per la lettura!

+0

Penso che sia probabilmente uno dei modi più puliti per andare. +1 – Mike

+0

@Mike Grazie per il follow-up, apprezzalo! –

Problemi correlati