Come posso condividere un DBConnection gestito su vari oggetti?

1

Sto implementando quello che pensavo fosse un semplice object wrapper attorno a un database in cui un oggetto "PartRecord" rappresenta una riga di una tabella di database.

Voglio che un client sia in grado di richiedere un dato record e di ricevere un oggetto che contenga i dati. Le proprietà di lettura ed esposizione dei dati sono un gioco da ragazzi, ma sto cercando di condividere l'oggetto MySqlConnection in modo coerente.

La mia iniziale implementazione ingenua era di mantenere un oggetto MySqlConnection privato in un modulo VB e di avere funzioni che le mie classi possono chiamare. Questo sarebbe effettivamente un singleton che qualsiasi mia classe potrebbe condividere.

Private MySqlCn as MySqlConnection

Friend Function GetMySqlConnection() as MySqlConnection
   If IsNothing(MySqlCn) then  MySqlCn = New MySqlConnection(cnstring)
   if MySqlCn.State = ConnectionState.Closed then MySqlConnection.Open(cnstring)
   Return MySqlCn
End Function

Friend Sub CloseMySqlConnection()
   If Not IsNothing(MySqlCn) AndAlso (Not MySqlCn.State = ConnectionState.Closed) Then  MySqlCn.Close
End Function

Con questo metodo puoi generalmente assicurarti che gli oggetti condividano una connessione e che rimangano aperti ogni volta che il database è disponibile, ma non puoi garantire che la connessione rimanga chiusa fino alla fine del programma.

Alcune alternative che ho provato:

  1. chiudi la connessione dopo ogni lettura

    'in PartRecord constructor:
    Using MySqlCn as MySqlConnection = GetMySqlConnection
      'read data
    End Using
    'this causes an open and close for every object you instantiate
    'obviously bad
    
  2. lasciatelo aperto

    'in constructor:
    Dim MySqlCn as MySqlConnection = GetMySqlConnection
    'read data
    'no close or dispose, open for the next guy
    'we are sharing an open connection, but
    'the connection won't really close until the program ends.
    'I think it will close then, but I was a lot more certain of it
    'in the COM days when I could wrap it in a class and
    'close it in the Terminate event when the reference count hit zero
    
  3. smetti di avere costruttori pubblici e hai una fabbrica di oggetti che implementa IDisposable per gestire la connessione

    'maybe not as nice for the client code
    'but does force a sharing of connections
    'and the client can call PartFactory.Close or PartFactory.Dispose when they are done
    'the PartFactory replaces the singleton
    'even though you could have more than one if you wanted
    
  4. la tua idea migliore. . .

Vorrei sapere se posso mantenere il mio stile preferito di costruttori di oggetti pubblici per un determinato record, ma gestisco comunque la connessione condivisa in modo responsabile. Penso che questo potrebbe essere impossibile dal momento che il gli oggetti standalone pubblicamente creabili non sanno quando il client viene mai fatto. Penso che dovrò trapelare la "connessione a un database e conoscere" l'astrazione al client o causare connessioni aperte o traffico di rete non necessario.

Inoltre, la documentazione indica che l'IDisposable viene solitamente utilizzato per cose non gestite (file, handle, ecc.). È appropriato / necessario per tenere un oggetto gestito come un oggetto .NET DBConnection? Mi piace il fatto che il client abbia la sintassi di Utilizzo e che io stia segnalando che deve essere chiuso in un modo standard, ma è la chiusura deterministica che sto cercando di ottenere e che merita il mio sforzo in un mondo di raccolta dei rifiuti? Non mi sento a mio agio nel dire "beh, la connessione si chiuderà alla fine quando nessuno la vuole" poiché questo componente sarà eventualmente utilizzato da molti diversi clienti all'interno dell'organizzazione. Cosa succede se si arrestano in modo anomalo o vengono utilizzati in un processo server a esecuzione prolungata?

Se è importante, questa è la prima di diverse classi wrapper DB. Qualunque schema io usi qui, voglio mantenere l'intero componente.

    
posta Mike 14.08.2014 - 04:38
fonte

1 risposta

1

Non condividere una connessione, a meno che tu non abbia più comandi in una singola transazione (che richiede di mantenere aperta la connessione). Apri / Chiudi dopo ogni azione che dichiari come "ovviamente scadente" è in realtà la strada da percorrere, poiché il pool di connessioni ti assicura di non perdere molto tempo (se non del tutto).

Sembra anche che tu stia reinventando un sistema di accesso ai dati, e sei sulla buona strada per farlo male (dato che non sai come risolvere questa semplice soluzione). Scegli uno degli shelving (ce ne sono molti gratuiti / OSS se non vuoi una soluzione commerciale) e dedica il tuo tempo a ciò che dovresti fare: scrivere logica aziendale invece di codice idraulico.

    
risposta data 14.08.2014 - 11:50
fonte

Leggi altre domande sui tag