sessionmaker()
è una fabbrica, è lì per incoraggiare l'immissione di opzioni di configurazione per la creazione di nuovi oggetti Session
in un unico posto. È facoltativo, in quanto è possibile chiamare semplicemente Session(bind=engine, expire_on_commit=False)
ogni volta che è necessario un nuovo Session
, tranne che è prolisso e dettagliato, e volevo fermare la proliferazione di "helper" su piccola scala che ognuno si avvicinava al problema di questa ridondanza in un modo nuovo e più confuso.
Quindi sessionmaker()
è solo uno strumento che consente di creare oggetti Session
quando necessario.
parte successiva. Penso che la domanda sia: qual è la differenza tra creare un nuovo Session()
in vari punti rispetto a usarne uno completamente. La risposta, non molto. Session
è un contenitore per tutti gli oggetti che hai inserito e quindi tiene anche traccia di una transazione aperta. Al momento si chiama rollback()
o commit()
, la transazione è finita, e il Session
non ha alcuna connessione al database fino a quando non è chiamato ad emettere nuovo SQL. I collegamenti in suo possesso ai vostri oggetti mappati sono riferimenti deboli, a condizione che gli oggetti sono puliti di modifiche in sospeso, quindi, anche a questo proposito il Session
sarà svuotarsi sul retro ad una marca stato di nuovo quando l'applicazione perde tutti i riferimenti agli oggetti mappati. Se lo lasci con l'impostazione predefinita "expire_on_commit"
, tutti gli oggetti sono scaduti dopo un commit. Se questo Session
si blocca in giro per cinque o venti minuti e tutti i tipi di cose sono cambiati nel database la volta successiva che lo utilizzerai, caricherà tutto lo stato nuovo di zecca la prossima volta che accederai a quegli oggetti anche se sono stati seduti in memoria per venti minuti.
Nelle applicazioni Web, di solito diciamo, hey, perché non si crea un nuovo Session
su ogni richiesta, invece di utilizzare sempre la stessa. Questa pratica assicura che la nuova richiesta inizi "pulita". Se alcuni oggetti della richiesta precedente non sono ancora stati raccolti, e se forse hai disattivato "expire_on_commit"
, forse lo stato della richiesta precedente è ancora in agguato, e quello stato potrebbe anche essere piuttosto vecchio. Se stai attento a lasciare expire_on_commit
acceso e chiamare definitivamente lo commit()
o il rollback()
alla fine della richiesta, allora va bene, ma se inizi con un nuovo Session
, allora non c'è nemmeno nessuna domanda che stai iniziando a pulire.Quindi l'idea di iniziare ogni richiesta con un nuovo Session
è davvero il modo più semplice per assicurarsi che tu stia iniziando di nuovo, e di rendere l'uso di expire_on_commit
praticamente facoltativo, poiché questo flag può comportare un sacco di SQL aggiuntivo per un'operazione che chiama commit()
nel mezzo di una serie di operazioni. Non sono sicuro se questo risponde alla tua domanda.
Il prossimo round è ciò che si parla di threading. Se la tua app è multithread, ti consigliamo di assicurarti che lo Session
in uso sia locale per ... qualcosa. scoped_session()
per impostazione predefinita lo rende locale al thread corrente. In un'app Web, la richiesta locale è in realtà ancora migliore. Flask-SQLAlchemy invia effettivamente una "funzione di ambito" personalizzata a scoped_session()
in modo da ottenere una sessione con ambito richiesta. L'applicazione piramide media attacca la sessione nel registro "richiesta". Quando si utilizzano schemi come questi, l'idea "crea nuova sessione su richiesta di avvio" continua a sembrare il modo più semplice per mantenere le cose dritte.
Wow, questo risponde a tutte le mie domande sulla parte SQLAlchemy e aggiunge anche alcune informazioni su Flask a nd Pyramid! Aggiunto bonus: gli sviluppatori rispondono;) Vorrei poter votare più di una volta. Grazie mille! – javex
Un chiarimento, se possibile: tu dici expire_on_commit "può incorrere in un sacco di extra SQL" ... puoi dare maggiori dettagli? Pensavo che expire_on_commit riguardasse solo ciò che accade nella RAM, non ciò che accade nel database. – Veky
expire_on_commit può risultare in più SQL se riutilizzi di nuovo la stessa Session, e alcuni oggetti sono ancora in giro in quella Session, quando li accederai avrai una SELECT a riga singola per ognuno di essi poiché ciascuno di essi individualmente aggiornare il loro stato in termini di nuova transazione. – zzzeek