System.Data.SQLite

Check-in [229ecb1203]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:More changes relating to IDisposable.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | IDisposablePattern
Files: files | file ages | folders
SHA1: 229ecb1203485224a40356db5c31d3ba8beda4b0
User & Date: mistachkin 2011-12-16 04:15:07.250
Context
2011-12-16
04:25
Compilation error fixes. check-in: 8dfdf59c72 user: mistachkin tags: IDisposablePattern
04:15
More changes relating to IDisposable. check-in: 229ecb1203 user: mistachkin tags: IDisposablePattern
03:32
Start of making sure that all core components containing IDisposable objects implement IDisposable and that they follow the established best-practices when doing so. check-in: c532a87e4d user: mistachkin tags: IDisposablePattern
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to System.Data.SQLite/SQLiteKeyReader.cs.
41
42
43
44
45
46
47
48
49


50
51
52
53
54
55
56
57
58
59
60
61
62
63













64
65
66
67
68
69
70
71
72
73
74
75
76












77
78
79
80
81
82
83
84







85



86
87
88
































89
90
91
92





















93
94
95
96
97
98
99
41
42
43
44
45
46
47


48
49
50













51
52
53
54
55
56
57
58
59
60
61
62
63
64












65
66
67
68
69
70
71
72
73
74
75
76
77







78
79
80
81
82
83
84
85
86
87
88



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149







-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    }

    /// <summary>
    /// A single sub-query for a given table/database.
    /// </summary>
    private sealed class KeyQuery : IDisposable
    {
      private SQLiteCommand _command;
      internal SQLiteDataReader _reader;
        private SQLiteCommand _command;
        internal SQLiteDataReader _reader;

      internal KeyQuery(SQLiteConnection cnn, string database, string table, params string[] columns)
      {
        using (SQLiteCommandBuilder builder = new SQLiteCommandBuilder())
        {
          _command = cnn.CreateCommand();
          for (int n = 0; n < columns.Length; n++)
          {
            columns[n] = builder.QuoteIdentifier(columns[n]);
          }
        }
        _command.CommandText = String.Format(CultureInfo.InvariantCulture, "SELECT {0} FROM [{1}].[{2}] WHERE ROWID = ?", String.Join(",", columns), database, table);
        _command.Parameters.AddWithValue(null, (long)0);
      }
        internal KeyQuery(SQLiteConnection cnn, string database, string table, params string[] columns)
        {
            using (SQLiteCommandBuilder builder = new SQLiteCommandBuilder())
            {
                _command = cnn.CreateCommand();
                for (int n = 0; n < columns.Length; n++)
                {
                    columns[n] = builder.QuoteIdentifier(columns[n]);
                }
            }
            _command.CommandText = String.Format(CultureInfo.InvariantCulture, "SELECT {0} FROM [{1}].[{2}] WHERE ROWID = ?", String.Join(",", columns), database, table);
            _command.Parameters.AddWithValue(null, (long)0);
        }

      internal bool IsValid
      {
        set
        {
          if (value != false) throw new ArgumentException();
          if (_reader != null)
          {
            _reader.Dispose();
            _reader = null;
          }
        }
      }
        internal bool IsValid
        {
            set
            {
                if (value != false) throw new ArgumentException();
                if (_reader != null)
                {
                    _reader.Dispose();
                    _reader = null;
                }
            }
        }

      internal void Sync(long rowid)
      {
        IsValid = false;
        _command.Parameters[0].Value = rowid;
        _reader = _command.ExecuteReader();
        _reader.Read();
      }
        internal void Sync(long rowid)
        {
            IsValid = false;
            _command.Parameters[0].Value = rowid;
            _reader = _command.ExecuteReader();
            _reader.Read();
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IDisposable Members
      public void Dispose()
      {
        IsValid = false;
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed)
                throw new ObjectDisposedException(typeof(KeyQuery).Name);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    ////////////////////////////////////
                    // dispose managed resources here...
                    ////////////////////////////////////

                    IsValid = false;

        if (_command != null) _command.Dispose();
        _command = null;
      }
                    if (_command != null) _command.Dispose();
                    _command = null;
                }

                //////////////////////////////////////
                // release unmanaged resources here...
                //////////////////////////////////////

                disposed = true;
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Destructor
        ~KeyQuery()
        {
            Dispose(false);
        }
        #endregion
    }

    /// <summary>
    /// This function does all the nasty work at determining what keys need to be returned for
    /// a given statement.
    /// </summary>
    /// <param name="cnn"></param>
255
256
257
258
259
260
261



































































262
263
264
265
266
267
268
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








      // Now we have all the additional columns we have to return in order to support
      // CommandBehavior.KeyInfo
      _keyInfo = new KeyInfo[keys.Count];
      keys.CopyTo(_keyInfo);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    #region IDisposable Members
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    #endregion

    ///////////////////////////////////////////////////////////////////////////////////////////////

    #region IDisposable "Pattern" Members
    private bool disposed;
    private void CheckDisposed() /* throw */
    {
#if THROW_ON_DISPOSED
        if (disposed)
            throw new ObjectDisposedException(typeof(SQLiteKeyReader).Name);
#endif
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    private void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                ////////////////////////////////////
                // dispose managed resources here...
                ////////////////////////////////////

                _stmt = null;

                if (_keyInfo == null) return;

                for (int n = 0; n < _keyInfo.Length; n++)
                {
                    if (_keyInfo[n].query != null)
                        _keyInfo[n].query.Dispose();
                }

                _keyInfo = null;
            }

            //////////////////////////////////////
            // release unmanaged resources here...
            //////////////////////////////////////

            disposed = true;
        }
    }
    #endregion

    ///////////////////////////////////////////////////////////////////////////////////////////////

    #region Destructor
    ~SQLiteKeyReader()
    {
        Dispose(false);
    }
    #endregion

    ///////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>
    /// How many additional columns of keyinfo we're holding
    /// </summary>
    internal int Count
    {
      get { return (_keyInfo == null) ? 0 : _keyInfo.Length; }
    }
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
427
428
429
430
431
432
433














434
435
436
437
438
439
440







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







      for (int n = 0; n < _keyInfo.Length; n++)
      {
        if (_keyInfo[n].query != null)
          _keyInfo[n].query.IsValid = false;
      }
    }

    public void Dispose()
    {
      _stmt = null;

      if (_keyInfo == null) return;

      for (int n = 0; n < _keyInfo.Length; n++)
      {
        if (_keyInfo[n].query != null)
          _keyInfo[n].query.Dispose();
      }
      _keyInfo = null;
    }

    internal string GetDataTypeName(int i)
    {
      Sync();
      if (_keyInfo[i].query != null) return _keyInfo[i].query._reader.GetDataTypeName(_keyInfo[i].column);
      else return "integer";
    }

Changes to System.Data.SQLite/SQLiteStatement.cs.
84
85
86
87
88
89
90





































































91
92
93
94
95
96
97
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







          }
          _paramNames[x] = s;
          _paramValues[x] = null;
        }
      }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    #region IDisposable Members
    /// <summary>
    /// Disposes and finalizes the statement
    /// </summary>
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    #endregion

    ///////////////////////////////////////////////////////////////////////////////////////////////

    #region IDisposable "Pattern" Members
    private bool disposed;
    private void CheckDisposed() /* throw */
    {
#if THROW_ON_DISPOSED
        if (disposed)
            throw new ObjectDisposedException(typeof(SQLiteStatement).Name);
#endif
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                ////////////////////////////////////
                // dispose managed resources here...
                ////////////////////////////////////

                if (_sqlite_stmt != null)
                {
                    _sqlite_stmt.Dispose();
                    _sqlite_stmt = null;
                }

                _paramNames = null;
                _paramValues = null;
                _sql = null;
                _sqlStatement = null;
            }

            //////////////////////////////////////
            // release unmanaged resources here...
            //////////////////////////////////////

            disposed = true;
        }
    }
    #endregion

    ///////////////////////////////////////////////////////////////////////////////////////////////

    #region Destructor
    ~SQLiteStatement()
    {
        Dispose(false);
    }
    #endregion

    ///////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>
    /// Called by SQLiteParameterCollection, this function determines if the specified parameter name belongs to
    /// this statement, and if so, keeps a reference to the parameter so it can be bound later.
    /// </summary>
    /// <param name="s">The parameter name to map</param>
    /// <param name="p">The parameter to assign it</param>
    internal bool MapParameter(string s, SQLiteParameter p)
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
182
183
184
185
186
187
188



















189
190
191
192
193
194
195







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







          _paramValues[n] = p;
          return true;
        }
      }
      return false;
    }

    #region IDisposable Members
    /// <summary>
    /// Disposes and finalizes the statement
    /// </summary>
    public void Dispose()
    {
      if (_sqlite_stmt != null)
      {
        _sqlite_stmt.Dispose();
      }
      _sqlite_stmt = null;
      
      _paramNames = null;
      _paramValues = null;
      _sql = null;
      _sqlStatement = null;
    }
    #endregion
    
    /// <summary>
    ///  Bind all parameters, making sure the caller didn't miss any
    /// </summary>
    internal void BindParameters()
    {
      if (_paramNames == null) return;

Changes to System.Data.SQLite/SQLiteTransaction.cs.
55
56
57
58
59
60
61














62





































63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124

125
126
127
128
129
130
131
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145
146
147
148















149
150
151
152
153

154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169







+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+



















-
+










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





-
+







+







          _cnn._transactionLevel--;
          _cnn = null;
          throw;
        }
      }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    #region IDisposable "Pattern" Members
    private bool disposed;
    private void CheckDisposed() /* throw */
    {
#if THROW_ON_DISPOSED
        if (disposed)
            throw new ObjectDisposedException(typeof(SQLiteTransaction).Name);
#endif
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>
    /// Disposes the transaction.  If it is currently active, any changes are rolled back.
    /// </summary>
    protected override void Dispose(bool disposing)
    {
        try
        {
            if (!disposed)
            {
                if (disposing)
                {
                    ////////////////////////////////////
                    // dispose managed resources here...
                    ////////////////////////////////////

                    if (IsValid(false))
                    {
                        IssueRollback();
                    }
                }

                //////////////////////////////////////
                // release unmanaged resources here...
                //////////////////////////////////////

                disposed = true;
            }
        }
        finally
        {
            base.Dispose(disposing);
        }
    }
    #endregion

    ///////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>
    /// Commits the current transaction.
    /// </summary>
    public override void Commit()
    {
      CheckDisposed();
      IsValid(true);

      if (_cnn._transactionLevel - 1 == 0)
      {
        using (SQLiteCommand cmd = _cnn.CreateCommand())
        {
          cmd.CommandText = "COMMIT";
          cmd.ExecuteNonQuery();
        }
      }
      _cnn._transactionLevel--;
      _cnn = null;
    }

    /// <summary>
    /// Returns the underlying connection to which this transaction applies.
    /// </summary>
    public new SQLiteConnection Connection
    {
      get { return _cnn; }
      get { CheckDisposed(); return _cnn; }
    }

    /// <summary>
    /// Forwards to the local Connection property
    /// </summary>
    protected override DbConnection DbConnection
    {
      get { return Connection; }
    }

    /// <summary>
    /// Disposes the transaction.  If it is currently active, any changes are rolled back.
    /// </summary>
    protected override void Dispose(bool disposing)
    {
      if (disposing)
      {
        if (IsValid(false))
        {
          IssueRollback();
        }
      }
      base.Dispose(disposing);
    }

    /// <summary>
    /// Gets the isolation level of the transaction.  SQLite only supports Serializable transactions.
    /// </summary>
    public override IsolationLevel IsolationLevel
    {
      get { return _level; }
      get { CheckDisposed(); return _level; }
    }

    /// <summary>
    /// Rolls back the active transaction.
    /// </summary>
    public override void Rollback()
    {
      CheckDisposed();
      IsValid(true);
      IssueRollback();
    }

    internal void IssueRollback()
    {
      SQLiteConnection cnn = Interlocked.Exchange(ref _cnn, null);
Changes to System.Data.SQLite/SR.Designer.cs.







1
2
3
4
5
6
7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
+
+
+
+
+
+
+







/********************************************************
 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.1
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.