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("&", "&").Replace("<", "<").Replace(">", "<").Replace(""", "\"").Replace(
123 "'", "‘");
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 }