in

UGISS Community

Il sito della community dello User Group Italiano di SQL Server

Transaction "implicita" in SQL Ce ?

Last post 12-29-2007 21.36 by Nick60. 4 replies.
Page 1 of 1 (5 items)
Sort Posts: Previous Next
  • 12-26-2007 11.50

    • Nick60
    • Top 50 Contributor
    • Joined on 06-04-2007
    • Posts 13
    • Points 200

    Transaction "implicita" in SQL Ce ?

    Su suggerimento di Davide Mauri riporto una domanda che mi sono fatto facendo alcune prove di importazione di file di testo in SQL Server, Express e Compact Edition. In particolare, debuggando un ciclo di inserimento in SQL Ce, mi sono accorto che interrompendo il ciclo col debugger e interrompendo l'esecuzione del programma, nessuna riga risultava importata nel database, come se internamente SQLCe in automatico crei una transaction che non viene commit-ata se non viene effettata la corretta chiusura della connection, perdendo tutte le modifiche.

    Qualcuno ne sa qualcosa al riguardo?

    ---------------------------------------------------------------------------

            public void LoadData()
            {
                string sourceConnectionString = Properties.Settings.Default.CBDataLogConnectionString;
                string destConnectionString = Properties.Settings.Default.WeightsConnectionString;
                using (OdbcConnection sourceConnection = new OdbcConnection(sourceConnectionString))
                {
                    sourceConnection.Open();
                    OdbcCommand commandSourceData = new OdbcCommand("SELECT * FROM CBDataLog.txt;", sourceConnection);
                    OdbcDataReader textFileDataReader = commandSourceData.ExecuteReader();
                    if (textFileDataReader.HasRows)
                    {
                        // Open the destination connection and insert into the SQLCe table
                        using (SqlCeConnection destinationConnection = new SqlCeConnection(destConnectionString))
                        {
                            destinationConnection.Open();
                            try
                            {
                                SqlCeCommand cmd = new SqlCeCommand();
                                cmd.Connection = destinationConnection;
                                cmd.CommandText = "INSERT INTO DataLog (LogLine) VALUES (?)";
                                cmd.Parameters.Add("@logLine", System.Data.SqlDbType.NVarChar);
                                cmd.Prepare();

                                stopWatch = Stopwatch.StartNew();
                                while (textFileDataReader.Read())
                                {
                                    cmd.Parameters[0].Value = textFileDataReader.GetValue(0).ToString();
                                    cmd.ExecuteNonQuery();
                                }
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex.Message);
                            }
                            finally
                            {
                                stopWatch.Stop();
                                textFileDataReader.Close();

                                // The connection objects are automatically closed at the end
                                // of the using blocks.
                            }
                        }
                    }
                }
            }

     

    • Post Points: 20
  • 12-27-2007 18.36 In reply to

    • robertob
    • Top 75 Contributor
    • Joined on 06-21-2007
    • Posts 3
    • Points 45

    Re: Transaction "implicita" in SQL Ce ?

    Ciao Nick60,

    il problema deriva dal fatto che SQLCE tiene un buffer delle modifiche (delle transazioni in realtá) in memoria per ragioni di performance. Il problema non é la non chiusura della connessione, ma il fatto che fermi il processo prima che lui faccia il flush delle modifiche rendendole persistenti.

    Fra i parametri della connection string puoi regolare questo funzionamento:

    1) Il parametro autoflush (true per default) indica appunto se far fare a lui il flush a intervalli regolari oppure disabilitare la funzione. Se la disabiliti ogni modifica fatta (o ogni transazione) viene committata immediatamente

    2) max buffer size: 640KB per default é il limite superato il quale viene fatto il flush su disco in caso di autoflush

    3) Flush interval: 10 secondi per default é l'intervallo di tempo ogni quanto lui fa il flush.

    Il fatto quindi che non vedi le modifiche deriva appunto dal flushing che viene fatto solo superati i 640KB di transazione o i 10 secondi di tempo. Ti consiglio di lasciare queste impostazioni al default nelle normali operazioni che fai sul DB in quanto migliorano le performance.

    Durante un aggiornamento massimo potresti aprire la connessione con questi parametri diversi (autoflush a false é sufficiente) per inserire un record alla volta.

    Se vuoi puoi anche gestire manualmente la transazione usando l'oggetto SqlCeTransaction, ma anche quando fai commit, se autoflush é true vengono rispettati i paramtri 2 e 3 che ti ho indicato.

    Un ultimo consiglio rispetto al codice: fai la Dispose() degli oggetti: commandSourceData, textFileDataReader e cmd. Per le connection non ne hai bisogno visto che usi la using.

     

    • Post Points: 20
  • 12-29-2007 11.47 In reply to

    • Nick60
    • Top 50 Contributor
    • Joined on 06-04-2007
    • Posts 13
    • Points 200

    Re: Transaction "implicita" in SQL Ce ?

    Devo ammettere (mea culpa) che ho postato solo per rispetto a Davide, ma dubitavo di avere una risposta.

    Invece la tua risposta è veramente completa e chiara.

    Quindi mille grazie a te per la risposta e a Davide per questa Community (che seguirò e alla quale parteciperò con maggior impegno).

    Per quanto riguarda Dispose(): avendo chiuso il textDataReader ed essendo (textDataReader, commandSourceData e cmd) oggetti managed, non ci pensa il Garbage Collector ?

    Io sto studiando su Pro ADO.NET 2.0 di Sahil Malik e fino ad ora (non l'ho ancora finito) non mi è parso di leggere nulla al riguardo. Ne tanto meno nei vari esempi che ho trovato su internet.

    Invece mi è abbastanza chiaro la necessità di "liberare" gli oggetti connection per utilizzare al meglio connection pool.

    Ma evidentemente devo avere un po' di confusione in testa. Potresti consigliarmi un articolo al riguardo?

    • Post Points: 20
  • 12-29-2007 21.09 In reply to

    • robertob
    • Top 75 Contributor
    • Joined on 06-21-2007
    • Posts 3
    • Points 45

    Re: Transaction "implicita" in SQL Ce ?

    Ciao Nick,

    per quanto riguarda la Dispose, la regola é semplice in .NET: se un oggetto che istanzi implementa IDisposable, chiama la Dispose appena non ti serve piú l'oggetto. Il pattern impone a chi scrive il componente di rilasciare tutto quello che ha allocato al suo interno. Chiamando la Dispose sei sicuro di far rilasciare al componente che usavi tutto il necessario.

    Se usi la using non hai bisogno di chiamare Dispose in quanto il compilatore emette un Try/Finally in cui nel blocco Finally viene chiamata la Dispose. Dai un occhio a questo piccolo articolo di Marco Russo:

    http://blogs.devleap.com/marco/archive/2005/01/10/2352.aspx
    http://blogs.devleap.com/marco/archive/2004/12/01/2087.aspx

    Sul sito trovi anche altri articoli di Marco sul CLR in quanto tale. Se sviluppi in ambiente mobile, su www.thinkmobile.it trovi forum e blog sull'argomento.

    Facendo la Close chiudi effettivamente la connessione piuttosto che il file che usi ma non é detto che vengano rilasciate tutte le risorse usate internamente dal componente, quindi se trovi la Dispose chiamala il prima possibile (non appena non ti serve piú l'oggetto).

    Chiudere la connessione é importante come dici tu anche per il Connection Pool, la Dispose infatti internamente chiama la Close se la connessione è aperta. Ti segnalo peró che SQLCE non fa pooling di connessioni, in quanto, anche se dalla versione 3.0 in poi consente piú connessioni, resta sempre un DB semplice e non nato per essere scalabile.

     

    • Post Points: 20
  • 12-29-2007 21.36 In reply to

    • Nick60
    • Top 50 Contributor
    • Joined on 06-04-2007
    • Posts 13
    • Points 200

    Re: Transaction "implicita" in SQL Ce ?

    Mille grazie.

    • Post Points: 5
Page 1 of 1 (5 items)
(C) 2007 User Group Italiano di SQL Server