C# 封装 System.Data.SQLite

参考1:

关于如何使用System.Data.SQLite的入门:

http://www.dreamincode.net/forums/topic/157830-using-sqlite-with-c%23/

 

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Data;
  4 using System.Data.SQLite;
  5 using System.Globalization;
  6 using System.Linq;
  7 using System.Windows.Forms;
  8 
  9 namespace Simple_Disk_Catalog
 10 {
 11     public class SQLiteDatabase
 12     {
 13         String DBConnection;
 14 
 15         private readonly SQLiteTransaction _sqLiteTransaction;
 16 
 17         private readonly SQLiteConnection _sqLiteConnection;
 18 
 19         private readonly bool _transaction;
 20 
 21         /// <summary>
 22         ///     Default Constructor for SQLiteDatabase Class.
 23         /// </summary>
 24         /// <param name="transaction">Allow programmers to insert, update and delete values in one transaction</param>
 25         public SQLiteDatabase(bool transaction = false)
 26         {
 27             _transaction = transaction;
 28             DBConnection = "Data Source=recipes.s3db";
 29             if (transaction)
 30             {
 31                 _sqLiteConnection = new SQLiteConnection(DBConnection);
 32                 _sqLiteConnection.Open();
 33                 _sqLiteTransaction = _sqLiteConnection.BeginTransaction();
 34             }
 35         }
 36 
 37         /// <summary>
 38         ///     Single Param Constructor for specifying the DB file.
 39         /// </summary>
 40         /// <param name="inputFile">The File containing the DB</param>
 41         public SQLiteDatabase(String inputFile)
 42         {
 43             DBConnection = String.Format("Data Source={0}", inputFile);
 44         }
 45 
 46         /// <summary>
 47         ///     Commit transaction to the database.
 48         /// </summary>
 49         public void CommitTransaction()
 50         {
 51             _sqLiteTransaction.Commit();
 52             _sqLiteTransaction.Dispose();
 53             _sqLiteConnection.Close();
 54             _sqLiteConnection.Dispose();
 55         }
 56 
 57         /// <summary>
 58         ///     Single Param Constructor for specifying advanced connection options.
 59         /// </summary>
 60         /// <param name="connectionOpts">A dictionary containing all desired options and their values</param>
 61         public SQLiteDatabase(Dictionary<String, String> connectionOpts)
 62         {
 63             String str = connectionOpts.Aggregate("", (current, row) => current + String.Format("{0}={1}; ", row.Key, row.Value));
 64             str = str.Trim().Substring(0, str.Length - 1);
 65             DBConnection = str;
 66         }
 67 
 68         /// <summary>
 69         ///     Allows the programmer to create new database file.
 70         /// </summary>
 71         /// <param name="filePath">Full path of a new database file.</param>
 72         /// <returns>true or false to represent success or failure.</returns>
 73         public static bool CreateDB(string filePath)
 74         {
 75             try
 76             {
 77                 SQLiteConnection.CreateFile(filePath);
 78                 return true;
 79             }
 80             catch (Exception e)
 81             {
 82                 MessageBox.Show(e.Message, e.GetType().ToString(), MessageBoxButtons.OK, MessageBoxIcon.Error);
 83                 return false;
 84             }
 85         }
 86 
 87         /// <summary>
 88         ///     Allows the programmer to run a query against the Database.
 89         /// </summary>
 90         /// <param name="sql">The SQL to run</param>
 91         /// <param name="allowDBNullColumns">Allow null value for columns in this collection.</param>
 92         /// <returns>A DataTable containing the result set.</returns>
 93         public DataTable GetDataTable(string sql, IEnumerable<string> allowDBNullColumns = null)
 94         {
 95             var dt = new DataTable();
 96             if (allowDBNullColumns != null)
 97                 foreach (var s in allowDBNullColumns)
 98                 {
 99                     dt.Columns.Add(s);
100                     dt.Columns[s].AllowDBNull = true;
101                 }
102             try
103             {
104                 var cnn = new SQLiteConnection(DBConnection);
105                 cnn.Open();
106                 var mycommand = new SQLiteCommand(cnn) {CommandText = sql};
107                 var reader = mycommand.ExecuteReader();
108                 dt.Load(reader);
109                 reader.Close();
110                 cnn.Close();
111             }
112             catch (Exception e)
113             {
114                 throw new Exception(e.Message);
115             }
116             return dt;
117         }
118 
119         public string RetrieveOriginal(string value)
120         {
121             return
122                 value.Replace("&amp;", "&").Replace("&lt;", "<").Replace("&gt;", "<").Replace("&quot;", "\"").Replace(
123                     "&apos;", "'");
124         }
125 
126         /// <summary>
127         ///     Allows the programmer to interact with the database for purposes other than a query.
128         /// </summary>
129         /// <param name="sql">The SQL to be run.</param>
130         /// <returns>An Integer containing the number of rows updated.</returns>
131         public int ExecuteNonQuery(string sql)
132         {
133             if (!_transaction)
134             {
135                 var cnn = new SQLiteConnection(DBConnection);
136                 cnn.Open();
137                 var mycommand = new SQLiteCommand(cnn) {CommandText = sql};
138                 var rowsUpdated = mycommand.ExecuteNonQuery();
139                 cnn.Close();
140                 return rowsUpdated;
141             }
142             else
143             {
144                 var mycommand = new SQLiteCommand(_sqLiteConnection) { CommandText = sql };
145                 return mycommand.ExecuteNonQuery();
146             }
147         }
148 
149         /// <summary>
150         ///     Allows the programmer to retrieve single items from the DB.
151         /// </summary>
152         /// <param name="sql">The query to run.</param>
153         /// <returns>A string.</returns>
154         public string ExecuteScalar(string sql)
155         {
156             if (!_transaction)
157             {
158                 var cnn = new SQLiteConnection(DBConnection);
159                 cnn.Open();
160                 var mycommand = new SQLiteCommand(cnn) {CommandText = sql};
161                 var value = mycommand.ExecuteScalar();
162                 cnn.Close();
163                 return value != null ? value.ToString() : "";
164             }
165             else
166             {
167                 var sqLiteCommand = new SQLiteCommand(_sqLiteConnection) { CommandText = sql };
168                 var value = sqLiteCommand.ExecuteScalar();
169                 return value != null ? value.ToString() : "";
170             }
171         }
172 
173         /// <summary>
174         ///     Allows the programmer to easily update rows in the DB.
175         /// </summary>
176         /// <param name="tableName">The table to update.</param>
177         /// <param name="data">A dictionary containing Column names and their new values.</param>
178         /// <param name="where">The where clause for the update statement.</param>
179         /// <returns>A boolean true or false to signify success or failure.</returns>
180         public bool Update(String tableName, Dictionary<String, String> data, String where)
181         {
182             String vals = "";
183             Boolean returnCode = true;
184             if (data.Count >= 1)
185             {
186                 vals = data.Aggregate(vals, (current, val) => current + String.Format(" {0} = '{1}',", val.Key.ToString(CultureInfo.InvariantCulture), val.Value.ToString(CultureInfo.InvariantCulture)));
187                 vals = vals.Substring(0, vals.Length - 1);
188             }
189             try
190             {
191                 ExecuteNonQuery(String.Format("update {0} set {1} where {2};", tableName, vals, where));
192             }
193             catch
194             {
195                 returnCode = false;
196             }
197             return returnCode;
198         }
199 
200         /// <summary>
201         ///     Allows the programmer to easily delete rows from the DB.
202         /// </summary>
203         /// <param name="tableName">The table from which to delete.</param>
204         /// <param name="where">The where clause for the delete.</param>
205         /// <returns>A boolean true or false to signify success or failure.</returns>
206         public bool Delete(String tableName, String where)
207         {
208             Boolean returnCode = true;
209             try
210             {
211                 ExecuteNonQuery(String.Format("delete from {0} where {1};", tableName, where));
212             }
213             catch (Exception fail)
214             {
215                 MessageBox.Show(fail.Message, fail.GetType().ToString(), MessageBoxButtons.OK, MessageBoxIcon.Error);
216                 returnCode = false;
217             }
218             return returnCode;
219         }
220 
221         /// <summary>
222         ///     Allows the programmer to easily insert into the DB
223         /// </summary>
224         /// <param name="tableName">The table into which we insert the data.</param>
225         /// <param name="data">A dictionary containing the column names and data for the insert.</param>
226         /// <returns>returns last inserted row id if it's value is zero than it means failure.</returns>
227         public long Insert(String tableName, Dictionary<String, String> data)
228         {
229             String columns = "";
230             String values = "";
231             String value;
232             foreach (KeyValuePair<String, String> val in data)
233             {
234                 columns += String.Format(" {0},", val.Key.ToString(CultureInfo.InvariantCulture));
235                 values += String.Format(" '{0}',", val.Value);
236             }
237             columns = columns.Substring(0, columns.Length - 1);
238             values = values.Substring(0, values.Length - 1);
239             try
240             {
241                 if (!_transaction)
242                 {
243                     var cnn = new SQLiteConnection(DBConnection);
244                     cnn.Open();
245                     var sqLiteCommand = new SQLiteCommand(cnn)
246                                         {
247                                             CommandText =
248                                                 String.Format("insert into {0}({1}) values({2});", tableName, columns,
249                                                               values)
250                                         };
251                     sqLiteCommand.ExecuteNonQuery();
252                     sqLiteCommand = new SQLiteCommand(cnn) { CommandText = "SELECT last_insert_rowid()" };
253                     value = sqLiteCommand.ExecuteScalar().ToString();
254                 }
255                 else
256                 {
257                     ExecuteNonQuery(String.Format("insert into {0}({1}) values({2});", tableName, columns, values));
258                     value = ExecuteScalar("SELECT last_insert_rowid()");
259                 }
260             }
261             catch (Exception fail)
262             {
263                 MessageBox.Show(fail.Message, fail.GetType().ToString(), MessageBoxButtons.OK, MessageBoxIcon.Error);
264                 return 0;
265             }
266             return long.Parse(value);
267         }
268 
269         /// <summary>
270         ///     Allows the programmer to easily delete all data from the DB.
271         /// </summary>
272         /// <returns>A boolean true or false to signify success or failure.</returns>
273         public bool ClearDB()
274         {
275             try
276             {
277                 var tables = GetDataTable("select NAME from SQLITE_MASTER where type='table' order by NAME;");
278                 foreach (DataRow table in tables.Rows)
279                 {
280                     ClearTable(table["NAME"].ToString());
281                 }
282                 return true;
283             }
284             catch
285             {
286                 return false;
287             }
288         }
289 
290         /// <summary>
291         ///     Allows the user to easily clear all data from a specific table.
292         /// </summary>
293         /// <param name="table">The name of the table to clear.</param>
294         /// <returns>A boolean true or false to signify success or failure.</returns>
295         public bool ClearTable(String table)
296         {
297             try
298             {
299                 ExecuteNonQuery(String.Format("delete from {0};", table));
300                 return true;
301             }
302             catch
303             {
304                 return false;
305             }
306         }
307 
308         /// <summary>
309         ///     Allows the user to easily reduce size of database.
310         /// </summary>
311         /// <returns>A boolean true or false to signify success or failure.</returns>
312         public bool CompactDB()
313         {
314             try
315             {
316                 ExecuteNonQuery("Vacuum;");
317                 return true;
318             }
319             catch (Exception)
320             {
321                 return false;
322             }
323         }
324     }
325 }
View Code

参考2:

关于如何正确使用System.Data.SQLite提高性能

SQLite .NET performance, how to speed up things?

You definitely need a transaction. If you don't, SQLite starts its own transaction for every insert command so you're effectively doing 86000 transactions as is.

It looks you're also opening and closing the connection each time, along with resetting the CommandText each time. This is unnecessary and doubtless slowing you down, it'll go much faster if you:

  • Open the connection once
  • Build the command once , adding the parameters to it once.
  • Start the transaction
  • Loop through, changing the parameter values only before calling ExecuteNonQuery
  • Commit the transaction.
  • Close the connection.

I think you could reduce your 20 minutes down to just a few seconds this way.

Edit: this is what I mean:

 1 public void InsertItems()
 2 {
 3     SQLiteConnection connection  = new SQLiteConnection(SomeConnectionString);
 4     SQLiteCommand command = connection.CreateCommand();
 5     SQLiteTransaction transaction = connection.BeginTransaction();
 6 
 7     command.CommandText = "INSERT OR IGNORE INTO Result "
 8 + "(RunTag, TopicId, DocumentNumber, Rank, Score) " +
 9   "VALUES (@RunTag, @TopicId, @DocumentNumber, @Rank, @Score)";
10 
11     command.Parameters.AddWithValue("@RunTag", "");
12     command.Parameters.AddWithValue("@TopicId", "");
13     command.Parameters.AddWithValue("@DocumentNumber", "");
14     command.Parameters.AddWithValue("@Rank", "");
15     command.Parameters.AddWithValue("@Score", "");
16 
17     foreach ( /* item to loop through and add to db */ )
18     {
19         InsertResultItem(runTag, topicId, documentNumber, rank, score, command);
20     }
21 
22     transaction.Commit();
23     command.Dispose();
24     connection.Dispose();
25 }
26 
27 public int InsertResultItem(string runTag, int topicId, string documentNumber, int rank, double score, SQLiteCommand command)
28 {
29     command.Parameters["@RunTag"].Value = runTag;
30     command.Parameters["@TopicId"].Value = topicId;
31     command.Parameters["@DocumentNumber"].Value = documentNumber;
32     command.Parameters["@Rank"].Value = rank;
33     command.Parameters["@Score"].Value = score;
34     return command.ExecuteNonQuery();
35 }
View Code

It only uses one connection, one transaction and one command, so all you're changing is the parameter values each time. 

 

我自己实现的一个简易版本:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Data.SQLite;
 7 
 8 namespace Utility
 9 {
10     /*Multithread safety: No!*/
11     public class SQLiteDB
12     {
13         private SQLiteConnection    m_db_conn;
14         private SQLiteTransaction    m_transaction;
15         private bool                m_is_transaction;
16         private SQLiteCommand        m_transaction_cmd;
17 
18         public SQLiteDB()
19         {
20             m_is_transaction = false;
21         }
22 
23         public SQLiteDB(string db_path)
24         {
25             m_is_transaction = false;
26             m_db_conn = new SQLiteConnection(string.Format("Data Source={0}", db_path));
27             m_db_conn.Open();
28         }
29         public void Open(string db_path)
30         {
31             m_db_conn = new SQLiteConnection(string.Format("Data Source={0}", db_path));
32             m_db_conn.Open();
33         }
34         public void Close()
35         {
36             if (m_db_conn.State != System.Data.ConnectionState.Closed)
37             {
38                 m_db_conn.Close();
39                 m_db_conn.Dispose();
40             }
41             if (null != m_transaction_cmd)
42             {
43                 m_transaction_cmd.Dispose();
44             }
45         }
46 
47         public void BeginTransaction()
48         {
49             m_is_transaction = true;
50             m_transaction_cmd = m_db_conn.CreateCommand();
51             m_transaction = m_db_conn.BeginTransaction();
52         }
53 
54         public void Commit()
55         {
56             if (m_is_transaction)
57             {
58                 m_transaction.Commit();
59                 m_transaction_cmd.Dispose();
60                 m_is_transaction = false;
61             }
62         }
63 
64         public void Rollback()
65         {
66             if (m_is_transaction)
67             {
68                 m_transaction.Rollback();
69                 m_transaction_cmd.Dispose();
70                 m_is_transaction = false;
71             }
72         }
73 
74         public int ExecuteNonQuery(string non_query_sql)
75         {
76             if (!m_is_transaction)
77             {
78                 SQLiteCommand sql_cmd = new SQLiteCommand(m_db_conn);
79                 sql_cmd.CommandText = non_query_sql;
80                 return sql_cmd.ExecuteNonQuery();
81             }
82             else
83             {
84                 m_transaction_cmd.CommandText = non_query_sql;
85                 return m_transaction_cmd.ExecuteNonQuery();
86             }
87         }
88     }
89 }

 

posted @ 2015-02-12 15:05  Eric Z  阅读(407)  评论(0编辑  收藏  举报