Sie sind auf Seite 1von 9

Overview

Adding a database to your application can be an easy way to store data and settings
between sessions for your program, but it is not always feasible to use a server based
DBMS to store your database. SQLite is a small, fast, and reliable database which can be
used without the end user having to install anything extra (achieved by referencing a
single .dll in your project). There are a few things we as developers must do to get started
with SQLite:
Install the .NET provider for SQLite from Sourceforge.net
Add a reference to System.Data.SQLite to your project (and mark the .dll to be
copied locally to your project)
Optionally Download a SQLite GUI Client and use it to design your DB (Feel
free to code it by hand if that is your preference)

If the above section made sense to you, feel free to jump down to the section titled
"Interacting with your Database", otherwise keep reading!

Getting Started
Referencing System.Data.SQLite
After you have installed the .NET provider for SQLite, you need to make sure that your
project can access the required .dll. In Visual Studio 2008, this can be done by selecting
"Project -> Add Reference..." from the main menu bar. A window will pop up, and under
the ".NET" tab, scroll down and find System.Data.SQLite.
Select it and click ok. It is now referenced in your project. The last thing we need to do is
make sure Visual Studio copies the .dll for System.Data.SQLite to the project folder,
which is necessary for SQLite to work without the provider. If the Solution Explorer
window is not currently visible, open it by selecting "View -> Solution Explorer" from
the main menu bar. Under the current project, click the + sign next to References to see a
list of all currently referenced libraries.
Right click the reference to System.Data.SQLite, and select "Properties". Set the property
"Copy Local" to true.

You have now successfully referenced SQLite, and it can be added to any file by "using
System.Data.SQLite;".

Using the SQLite GUI Client


SQLite Administrator is a very straightforward Client, and I am not going to go into
much detail with its use. I will however note a few things that were not immediately
evident to me when I first used it.
SQLite does not currently support foreign key constraints. Therefore SQLite
Administrator does not have any way of linking tables via Foreign Key. That is
certainly something to keep in mind.
The box on the left hand side is for viewing the current Database and all of it's
objects. If you see something you don't want to see, or don't see something you
want to see, the buttons at the top of the box are toggle switches for tables, views,
triggers, indexes, and so on. Since there are no tooltips, you'll just have to play
around to figure out which is which function.

Interacting with
your Database
Once the database is set up, it is time to begin reading from it and writing to it. In order to
facilitate the interaction with the DB, I have written a helper class. It should be noted that
a portion of this code is adapted from sample code in this tutorial by Mike Duncan. The
Methods GetDataTable(), ExecuteNonQuery(), and ExecuteScalar() are his code and not
mine.

Using the SQLiteDatabase Helper


Class
SQLiteDatabase.cs
001 using System;

002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047

using
using
using
using

System.Collections.Generic;
System.Data;
System.Data.SQLite;
System.Windows.Forms;

class SQLiteDatabase
{
String dbConnection;
/// <summary>
///
Default Constructor for SQLiteDatabase Class.
/// </summary>
public SQLiteDatabase()
{
dbConnection = "Data Source=recipes.s3db";
}
/// <summary>
///
Single Param Constructor for specifying the DB file.
/// </summary>
/// <param name="inputFile">The File containing the DB</param>
public SQLiteDatabase(String inputFile)
{
dbConnection = String.Format("Data Source={0}", inputFile);
}
/// <summary>
///
Single Param Constructor for specifying advanced
connection options.
/// </summary>
/// <param name="connectionOpts">A dictionary containing all
desired options and their values</param>
public SQLiteDatabase(Dictionary<String, String> connectionOpts)
{
String str = "";
foreach (KeyValuePair<String, String> row in connectionOpts)
{
str += String.Format("{0}={1}; ", row.Key, row.Value);
}
str = str.Trim().Substring(0, str.Length - 1);
dbConnection = str;
}
/// <summary>
///
Allows the programmer to run a query against the
Database.
/// </summary>
/// <param name="sql">The SQL to run</param>
/// <returns>A DataTable containing the result set.</returns>

048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093

public DataTable GetDataTable(string sql)


{
DataTable dt = new DataTable();
try
{
SQLiteConnection cnn = new
SQLiteConnection(dbConnection);
cnn.Open();
SQLiteCommand mycommand = new SQLiteCommand(cnn);
mycommand.CommandText = sql;
SQLiteDataReader reader = mycommand.ExecuteReader();
dt.Load(reader);
reader.Close();
cnn.Close();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return dt;
}
/// <summary>
///
Allows the programmer to interact with the database for
purposes other than a query.
/// </summary>
/// <param name="sql">The SQL to be run.</param>
/// <returns>An Integer containing the number of rows
updated.</returns>
public int ExecuteNonQuery(string sql)
{
SQLiteConnection cnn = new SQLiteConnection(dbConnection);
cnn.Open();
SQLiteCommand mycommand = new SQLiteCommand(cnn);
mycommand.CommandText = sql;
int rowsUpdated = mycommand.ExecuteNonQuery();
cnn.Close();
return rowsUpdated;
}

DB.

/// <summary>
///
Allows the programmer to retrieve single items from the
/// </summary>
/// <param name="sql">The query to run.</param>
/// <returns>A string.</returns>
public string ExecuteScalar(string sql)
{
SQLiteConnection cnn = new SQLiteConnection(dbConnection);
cnn.Open();

094
095
096
097
098
099
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

SQLiteCommand mycommand = new SQLiteCommand(cnn);


mycommand.CommandText = sql;
object value = mycommand.ExecuteScalar();
cnn.Close();
if (value != null)
{
return value.ToString();
}
return "";
}
/// <summary>
///
Allows the programmer to easily update rows in the DB.
/// </summary>
/// <param name="tableName">The table to update.</param>
/// <param name="data">A dictionary containing Column names and
their new values.</param>
/// <param name="where">The where clause for the update
statement.</param>
/// <returns>A boolean true or false to signify success or
failure.</returns>
public bool Update(String tableName, Dictionary<String, String>
data, String where)
{
String vals = "";
Boolean returnCode = true;
if (data.Count >= 1)
{
foreach (KeyValuePair<String, String> val in data)
{
vals += String.Format(" {0} = '{1}',",
val.Key.ToString(), val.Value.ToString());
}
vals = vals.Substring(0, vals.Length - 1);
}
try
{
this.ExecuteNonQuery(String.Format("update {0} set {1}
where {2};", tableName, vals, where));
}
catch
{
returnCode = false;
}
return returnCode;
}
/// <summary>
///
Allows the programmer to easily delete rows from the DB.
/// </summary>

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
170
171
172
173
174
175
176
177
178
179

/// <param name="tableName">The table from which to


delete.</param>
/// <param name="where">The where clause for the delete.</param>
/// <returns>A boolean true or false to signify success or
failure.</returns>
public bool Delete(String tableName, String where)
{
Boolean returnCode = true;
try
{
this.ExecuteNonQuery(String.Format("delete from {0}
where {1};", tableName, where));
}
catch (Exception fail)
{
MessageBox.Show(fail.Message);
returnCode = false;
}
return returnCode;
}
/// <summary>
///
Allows the programmer to easily insert into the DB
/// </summary>
/// <param name="tableName">The table into which we insert the
data.</param>
/// <param name="data">A dictionary containing the column names
and data for the insert.</param>
/// <returns>A boolean true or false to signify success or
failure.</returns>
public bool Insert(String tableName, Dictionary<String, String>
data)
{
String columns = "";
String values = "";
Boolean returnCode = true;
foreach (KeyValuePair<String, String> val in data)
{
columns += String.Format(" {0},", val.Key.ToString());
values += String.Format(" '{0}',", val.Value);
}
columns = columns.Substring(0, columns.Length - 1);
values = values.Substring(0, values.Length - 1);
try
{
this.ExecuteNonQuery(String.Format("insert into {0}({1})
values({2});", tableName, columns, values));
}
catch(Exception fail)
{

180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

MessageBox.Show(fail.Message);
returnCode = false;
}
return returnCode;
}
/// <summary>
///
Allows the programmer to easily delete all data from the
DB.
/// </summary>
/// <returns>A boolean true or false to signify success or
failure.</returns>
public bool ClearDB()
{
DataTable tables;
try
{
tables = this.GetDataTable("select NAME from
SQLITE_MASTER where type='table' order by NAME;");
foreach (DataRow table in tables.Rows)
{
this.ClearTable(table["NAME"].ToString());
}
return true;
}
catch
{
return false;
}
}
/// <summary>
///
Allows the user to easily clear all data from a specific
table.
/// </summary>
/// <param name="table">The name of the table to clear.</param>
/// <returns>A boolean true or false to signify success or
failure.</returns>
public bool ClearTable(String table)
{
try
{
this.ExecuteNonQuery(String.Format("delete from {0};",
table));
return true;
}
catch
{
return false;

224
225
226 }

}
}

Usage:
Query:
01 try
02 {
03
db = new SQLiteDatabase();
04
DataTable recipe;
String query = "select NAME \"Name\",
05
DESCRIPTION \"Description\",";
query += "PREP_TIME \"Prep Time\", COOKING_TIME \"Cooking
06
Time\"";
07
query += "from RECIPE;";
08
recipe = db.GetDataTable(query);
09
// The results can be directly applied to a DataGridView control
10
recipeDataGrid.DataSource = recipe;
11
/*
12
// Or looped through for some other reason
13
foreach (DataRow r in recipe.Rows)
14
{
15
MessageBox.Show(r["Name"].ToString());
16
MessageBox.Show(r["Description"].ToString());
17
MessageBox.Show(r["Prep Time"].ToString());
18
MessageBox.Show(r["Cooking Time"].ToString());
19
}
20
21
*/
22 }
23 catch(Exception fail)
24 {
25
String error = "The following error has occurred:\n\n";
26
error += fail.Message.ToString() + "\n\n";
27
MessageBox.Show(error);
28
this.Close();
29 }

Insert:
01 db = new SQLiteDatabase();
02 Dictionary<String, String> data = new Dictionary<String, String>();

03
04
05
06
07
08
09
10
11
12
13
14
15

data.Add("NAME", nameTextBox.Text);
data.Add("DESCRIPTION", descriptionTextBox.Text);
data.Add("PREP_TIME", prepTimeTextBox.Text);
data.Add("COOKING_TIME", cookingTimeTextBox.Text);
data.Add("COOKING_DIRECTIONS", "Placeholder");
try
{
db.Insert("RECIPE", data);
}
catch(Exception crap)
{
MessageBox.Show(crap.Message);
}

Update:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15

db = new SQLiteDatabase();
Dictionary<String, String> data = new Dictionary<String, String>();
DataTable rows;
data.Add("NAME", nameTextBox.Text);
data.Add("DESCRIPTION", descriptionTextBox.Text);
data.Add("PREP_TIME", prepTimeTextBox.Text);
data.Add("COOKING_TIME", cookingTimeTextBox.Text);
try
{
db.Update("RECIPE", data, String.Format("RECIPE.ID = {0}",
this.RecipeID));
}
catch(Exception crap)
{
MessageBox.Show(crap.Message);
}

Delete:
1
2
3
4

db = new SQLiteDatabase();
String recipeID = "12";
db.Delete("RECIPE", String.Format("ID = {0}", recipeID));
db.Delete("HAS_INGREDIENT", String.Format("ID = {0}", recipeID));

This post has been edited by JackOfAllTrades: 13 September 2010 - 08:59 AM