SQLiteConnection.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. using System;
  2. using System.Data;
  3. using System.Collections;
  4. using System.Text;
  5. using System.IO;
  6. using System.Diagnostics;
  7. using System.Runtime.InteropServices;
  8. using System.Data.SQLiteClient.Native;
  9. using System.Globalization;
  10. namespace System.Data.SQLiteClient
  11. {
  12. sealed public class SQLiteConnection : IDbConnection, IDisposable
  13. {
  14. private ConnectionState _State;
  15. private SQLiteCommandCollection _Commands;
  16. private String _ConnectionString;
  17. private int _DataReaderCount;
  18. private IFormatProvider _UniversalProvider;
  19. private int _LastChangesCount;
  20. private NativeMethods _NativeMethods;
  21. private SQLiteConnectionStringBuilder _ConnectionStringBuilder;
  22. private string _Version;
  23. public SQLiteConnection()
  24. {
  25. _Commands = new SQLiteCommandCollection();
  26. _ConnectionString = "";
  27. _DataReaderCount = 0;
  28. _UniversalProvider = CultureInfo.InvariantCulture;
  29. _LastChangesCount = 0;
  30. _State = ConnectionState.Closed;
  31. _NativeMethods = null;
  32. _Version = "";
  33. }
  34. public SQLiteConnection(String connectionString) : this()
  35. {
  36. _ConnectionStringBuilder = new SQLiteConnectionStringBuilder(connectionString);
  37. ConnectionString = connectionString;
  38. }
  39. public SQLiteConnection(SQLiteConnectionStringBuilder builder) : this()
  40. {
  41. _ConnectionStringBuilder = builder;
  42. _ConnectionString = builder.ToString();
  43. }
  44. public void Dispose()
  45. {
  46. Close();
  47. }
  48. internal NativeMethods NativeMethods
  49. {
  50. get { return _NativeMethods; }
  51. }
  52. internal DateTimeFormat DateTimeFormat
  53. {
  54. get { return _ConnectionStringBuilder.DateTimeFormat; }
  55. }
  56. internal IFormatProvider UniversalFormatProvider
  57. {
  58. get { return _UniversalProvider; }
  59. }
  60. internal int LastChangesCount
  61. {
  62. get { return _LastChangesCount; }
  63. set { _LastChangesCount = value; }
  64. }
  65. public string ConnectionString
  66. {
  67. get
  68. {
  69. return _ConnectionString;
  70. }
  71. set
  72. {
  73. if (value == null || value == "") throw new ArgumentNullException("ConnectionString cannot be null or empty.");
  74. if (_State != ConnectionState.Closed) throw new SQLiteException("The connection is allready opened.");
  75. _ConnectionString = value;
  76. _ConnectionStringBuilder = new SQLiteConnectionStringBuilder(value);
  77. }
  78. }
  79. public int ConnectionTimeout
  80. {
  81. get { return 0; }
  82. }
  83. public String Database
  84. {
  85. get { return _ConnectionStringBuilder.DataSource; }
  86. }
  87. public ConnectionState State
  88. {
  89. get { return _State; }
  90. }
  91. public string SQLiteVersion
  92. {
  93. get { return _Version; }
  94. }
  95. internal void AttachCommand(SQLiteCommand command)
  96. {
  97. _Commands.Add(command);
  98. }
  99. internal void DetachCommand(SQLiteCommand command)
  100. {
  101. _Commands.Remove(command);
  102. }
  103. internal void AttachDataReader(SQLiteDataReader reader)
  104. {
  105. _DataReaderCount ++;
  106. _State = ConnectionState.Executing;
  107. }
  108. internal void DetachDataReader(SQLiteDataReader reader)
  109. {
  110. _DataReaderCount--;
  111. if (_DataReaderCount == 0 && _State == ConnectionState.Executing) _State = ConnectionState.Open;
  112. if((reader._CommandBehavior & CommandBehavior.CloseConnection) != 0)
  113. {
  114. if (_DataReaderCount == 0)
  115. {
  116. Close();
  117. }
  118. else
  119. {
  120. throw new SQLiteException("There is allready another DataReader opened. Connection cannot be closed by closing DataReader.");
  121. }
  122. }
  123. }
  124. IDbTransaction IDbConnection.BeginTransaction()
  125. {
  126. return BeginTransaction();
  127. }
  128. IDbTransaction IDbConnection.BeginTransaction(IsolationLevel level)
  129. {
  130. return BeginTransaction(level);
  131. }
  132. public SQLiteTransaction BeginTransaction()
  133. {
  134. if (_State != ConnectionState.Open)
  135. {
  136. throw new SQLiteException("The connection is not opened.");
  137. }
  138. return new SQLiteTransaction(this);
  139. }
  140. public SQLiteTransaction BeginTransaction(IsolationLevel level)
  141. {
  142. return BeginTransaction();
  143. }
  144. public void ChangeDatabase(String newDatabase)
  145. {
  146. throw new NotSupportedException();
  147. }
  148. public void Open()
  149. {
  150. if (_State != ConnectionState.Closed) throw new SQLiteException("The connection is not closed.");
  151. if (File.Exists(_ConnectionStringBuilder.DataSource))
  152. {
  153. if (_ConnectionStringBuilder.NewDatabase)
  154. {
  155. // Try to delete existing file
  156. try
  157. {
  158. File.Delete(_ConnectionStringBuilder.DataSource);
  159. File.Delete(String.Concat(_ConnectionStringBuilder.DataSource, "-journal"));
  160. }
  161. catch (IOException)
  162. {
  163. throw new SQLiteException ("Cannot create new file, the existing file is in use.");
  164. }
  165. }
  166. }
  167. else
  168. {
  169. if (!_ConnectionStringBuilder.NewDatabase)
  170. {
  171. throw new SQLiteException(String.Format("File '{0}' does not exist. Use ConnectionString parameter NewDatabase=True to create new file or enter the full path name.", _ConnectionStringBuilder.DataSource));
  172. }
  173. }
  174. if (_ConnectionStringBuilder.Emulator)
  175. {
  176. _NativeMethods = new WindowsMethods(_ConnectionStringBuilder.Encoding);
  177. }
  178. else
  179. {
  180. _NativeMethods = new SymbianMethods(_ConnectionStringBuilder.Encoding);
  181. }
  182. SQLiteCode res = _NativeMethods.Open(_ConnectionStringBuilder.DataSource);
  183. if (res != SQLiteCode.Ok)
  184. {
  185. try
  186. {
  187. if (_NativeMethods.ErrorCode() != SQLiteCode.Ok)
  188. {
  189. throw new SQLiteException(string.Format("Error opening database {0}.\r\n {1}", _ConnectionStringBuilder.DataSource, _NativeMethods.ErrorMessage()));
  190. }
  191. }
  192. finally
  193. {
  194. _NativeMethods.Dispose();
  195. _NativeMethods = null;
  196. }
  197. }
  198. _Version = _NativeMethods.SQliteVersion();
  199. _State = ConnectionState.Open;
  200. SQLiteCommand cmd = CreateCommand(string.Format("pragma synchronous = {0}", _ConnectionStringBuilder.SynchronousMode));
  201. cmd.ExecuteNonQuery();
  202. cmd = CreateCommand(string.Format("pragma cache_size = {0}", _ConnectionStringBuilder.CacheSize));
  203. cmd.ExecuteNonQuery();
  204. }
  205. public void Close ()
  206. {
  207. if (_State != ConnectionState.Closed)
  208. {
  209. _Commands.Dispose();
  210. _State = ConnectionState.Closed;
  211. _NativeMethods.Dispose();
  212. }
  213. }
  214. IDbCommand IDbConnection.CreateCommand()
  215. {
  216. return new SQLiteCommand ("", this);
  217. }
  218. public SQLiteCommand CreateCommand()
  219. {
  220. return new SQLiteCommand ("", this);
  221. }
  222. public SQLiteCommand CreateCommand(string commandText)
  223. {
  224. return new SQLiteCommand(commandText, this);
  225. }
  226. }
  227. }