用 C# 访问 SQLite 入门 (1)
SQLite 在 VS C# 环境下的开发,网上已经有很多教程。我也是从这些教程开始学习的。而要专门写下这一篇,是因为按照网上教程的例子,会遇到一些问题,特别是一些细节的设置,没有具体涉及,往往就让我这样的初学者碰壁,明明是全部照搬的却不断出错而不知解决方法。这里就特别记录和注明我遇到的问题和解决方法,让其他的初学者可以仿照处理。
这里用到的例子和C#语句,都是从网上来的。
1. 下载安装 Sqlite ADO.NET
可以从 sourceforge 下载: http://sourceforge.net/projects/sqlite-dotnet2/
安装则是按提示进行即可
2. 建立Sqlite 数据库文件
我是在 Firefox 下,安装 SQLite Manager 来建立的。例如,建立一个 Books.sqlite 数据库文件:
从 Firefox 菜单 启动 SQLite Manager, 点 Database -> New Database, 输入数据库文件名
然后选择保存路径,例如 把文件保存到 桌面。
点 Execute SQL , 在 Enter SQL 区域 输入建库语句,如下:
- CREATE TABLE Book
- (
- ID INTEGER,
- BookName VARCHAR(50),
- Price DOUBLE,
- Rowguid VARCHAR(70),
- PRIMARY KEY(ID)
- )
然后点 Run SQL 即可完成建库工作。
在 SQLite Manager 点 Database -> Close Database, 关闭数据库并退出 SQLite Manager.
3. 新建 C# Project, 引用 sqlite
新建一个 VC# 的 Windows Form Application, 命名为 dg2 (或其他名)。
在 VS 菜单, 点 Project -> Add Reference
在 .NET 下找到 System.Data.SQLite, 点 OK.
注意了,重点步骤:
在 VS 的右边,Soultion Explor , References, 点 System.Data.SQLite
然后, 在下面的 Properties 的 Copy Local, 选 True
这一步很重要,如果没有这个设置,以后在Debug 或 Build 后试运行,会提示找不到 System.Data.SQLite
4. 加入数据库文件
把数据库文件放到一个目录下。先建目录:
在右边的 Solution Explorer, 在Project名字上点鼠标右键,
在弹出选项,选 Add -> New Folder
然后,给 New Folder 改个名字, 例如 db
把数据库文件加入到这个 db 目录之下。
在 db 目录名上 点鼠标右键,在弹出菜单 选 Add -> Existing Item
然后,在打开的文件对话框,找到以前建立的数据库文件。如上面所示的例子,新建的 Books.sqlite 数据库文件是放在 桌面,我们就从桌面找到和选中这个文件,点 Add,即可把这个文件加入 db 目录下。
点一下 这个数据库文件,在下面的 Properties 选项 Copy to output Directory , 必须选 Copy always
注意: 这个设置很重要。否则就找不到数据库文件。
5. 建立相关类文件 Class
在 VS 菜单, 点 Project -> Add Class, 给个名字 Book.cs , 点 Add, 然后输入对 Book类 的定义:
- public class Book
- {
- private int id;
- private string bookName;
- private decimal price;
- private string rowguid;
- public int ID
- {
- get { return id; }
- set { id = value; }
- }
- public string BookName
- {
- get { return bookName; }
- set { bookName = value; }
- }
- public decimal Price
- {
- get { return price; }
- set { price = value; }
- }
- public string Rowguid
- {
- get { return rowguid; }
- set { rowguid = value; }
- }
- public Book()
- { }
- public Book(int _id, string _bookname, decimal _price, string _rowguid)
- {
- id = _id;
- bookName = _bookname;
- price = _price;
- rowguid = _rowguid;
- }
- }
保存。
类似步骤,输入 数据库操作类: BookDAL.cs
- public class BookDAL
- {
- public static bool CreateBook(Book book)
- {
- try
- {
- SQLiteConnection conn = new SQLiteConnection("Data Source=db/Books.sqlite;");
- conn.Open();
- SQLiteCommand cmd = conn.CreateCommand();
- cmd.CommandText = "INSERT INTO Book(ID, BookName, Price, Rowguid) VALUES(@ID1, @BookName1, @Price1, @Rowguid1)";
- cmd.Parameters.Add(new SQLiteParameter("ID1", book.ID));
- cmd.Parameters.Add(new SQLiteParameter("BookName1", book.BookName));
- cmd.Parameters.Add(new SQLiteParameter("Price1", book.Price));
- cmd.Parameters.Add(new SQLiteParameter("Rowguid1", book.Rowguid));
- int i = cmd.ExecuteNonQuery();
- return i == 1;
- }
- catch (SQLiteException se)
- {
- MessageBox.Show(se.Message + " " + se.Source + " " + se.StackTrace + " " + se.Data);
- return false;
- }
- catch (ArgumentException ae)
- {
- MessageBox.Show(ae.Message + " " + ae.Source + " " + ae.StackTrace + " " + ae.Data);
- return false;
- }
- catch (Exception ex)
- {
- //Do any logging operation here if necessary
- MessageBox.Show(ex.Message + " " + ex.Source + " " + ex.StackTrace + " " + ex.Data);
- return false;
- }
- }
- public static bool UpdateBookByID(Book book)
- {
- try
- {
- using (SQLiteConnection conn = new SQLiteConnection("Data Source=db/Books.sqlite;"))
- {
- conn.Open();
- SQLiteCommand cmd = conn.CreateCommand();
- cmd.CommandText = "update Book set BookName=@BookName1,Price=@Price1, Rowguid=@Rowguid1 where ID=@ID1;";
- cmd.Parameters.Add(new SQLiteParameter("ID1", book.ID));
- cmd.Parameters.Add(new SQLiteParameter("BookName1", book.BookName));
- cmd.Parameters.Add(new SQLiteParameter("Price1", book.Price));
- cmd.Parameters.Add(new SQLiteParameter("Rowguid1", book.Rowguid));
- int i = cmd.ExecuteNonQuery();
- return i == 1;
- }
- }
- catch (ArgumentException ae)
- {
- MessageBox.Show(ae.Message + " " + ae.Source + " " + ae.StackTrace);
- return false;
- }
- catch (Exception ex)
- {
- //Do any logging operation here if necessary
- MessageBox.Show(ex.Message);
- return false;
- }
- }
- public static bool UpdateBookByGuid(Book book)
- {
- try
- {
- using (SQLiteConnection conn = new SQLiteConnection("Data Source=db/Books.sqlite;"))
- {
- conn.Open();
- SQLiteCommand cmd = conn.CreateCommand();
- cmd.CommandText = "update Book set ID=@ID1,BookName=@BookName1,Price=@Price1 where Rowguid=@Rowguid1;";
- cmd.Parameters.Add(new SQLiteParameter("ID1", book.ID));
- cmd.Parameters.Add(new SQLiteParameter("BookName1", book.BookName));
- cmd.Parameters.Add(new SQLiteParameter("Price1", book.Price));
- cmd.Parameters.Add(new SQLiteParameter("Rowguid1", book.Rowguid));
- int i = cmd.ExecuteNonQuery();
- return i == 1;
- }
- }
- catch (ArgumentException ae)
- {
- MessageBox.Show(ae.Message + " " + ae.Source + " " + ae.StackTrace);
- return false;
- }
- catch (Exception ex)
- {
- //Do any logging operation here if necessary
- MessageBox.Show(ex.Message);
- return false;
- }
- }
- public static bool DeleteBook(int ID)
- {
- try
- {
- using (SQLiteConnection conn = new SQLiteConnection("Data Source=db/Books.sqlite;"))
- {
- conn.Open();
- SQLiteCommand cmd = conn.CreateCommand();
- cmd.CommandText = "delete from Book where ID=@ID;";
- cmd.Parameters.Add(new SQLiteParameter("ID", ID));
- int i = cmd.ExecuteNonQuery();
- return i == 1;
- }
- }
- catch (ArgumentException ae)
- {
- MessageBox.Show(ae.Message + " " + ae.Source + " " + ae.StackTrace);
- return false;
- }
- catch (Exception ex)
- {
- //Do any logging operation here if necessary
- MessageBox.Show(ex.Message);
- return false;
- }
- }
- public static Book GetBookByID(int ID)
- {
- try
- {
- using (SQLiteConnection conn = new SQLiteConnection("Data Source=db/Books.sqlite;"))
- {
- conn.Open();
- SQLiteCommand cmd = conn.CreateCommand();
- cmd.CommandText = "select * from Book where ID=@ID;";
- cmd.Parameters.Add(new SQLiteParameter("ID", ID));
- SQLiteDataReader dr = cmd.ExecuteReader();
- if (dr.Read())
- {
- Book book = new Book();
- book.ID = dr.GetInt32(0);
- book.BookName = dr.GetString(1);
- book.Price = dr.GetDecimal(2);
- return book;
- }
- else
- return null;
- }
- }
- catch (ArgumentException ae)
- {
- MessageBox.Show(ae.Message + " " + ae.Source + " " + ae.StackTrace);
- return null;
- }
- catch (Exception ex)
- {
- //Do any logging operation here if necessary
- throw new Exception(ex.Message);
- }
- }
- public static DataTable GetAllBook()
- {
- DataTable dt = new DataTable();
- try
- {
- SQLiteConnection conn = new SQLiteConnection("Data Source=db/Books.sqlite;");
- conn.Open();
- SQLiteCommand cmd = new SQLiteCommand(conn);
- cmd.CommandText = "SELECT * FROM Book";
- cmd.CommandType = CommandType.Text;
- //Console.WriteLine(cmd.CommandText);
- SQLiteDataReader dr = cmd.ExecuteReader();
- if (dr.HasRows)
- {
- dt.Load(dr);
- }
- else {
- //throw new NullReferenceException("No Record Available.");
- }
- dr.Close();
- conn.Close();
- }
- catch (ArgumentException ae)
- {
- MessageBox.Show(ae.Message + " " + ae.Source + " " + ae.StackTrace + " " + ae.Data);
- }
- catch (Exception ex)
- {
- //throw new Exception(ex.Message);
- MessageBox.Show(ex.Message + " " + ex.Source + " " + ex.StackTrace + " " + ex.Data);
- }
- return dt;
- }
- }
在数据库操作类,因为涉及数据库的操作,要在 using 部分,必须加入 using System.Data. SQLite 的引用等语句。
- using System.Data;
- using System.Data.SQLite;
- using System.Windows.Forms;
注意了:
初学者都喜欢用别人的代码来做练习,拷贝过来,粘贴上去,可减少敲键盘的时间。但是,在网页上拷贝代码,然后贴到 VS里,会引起很多问题。例如 html 的控制符,空格等等,导致以后程序运行出错,而且不知道错误在哪里。明明在屏幕上看到人家的代码 与 你的代码是一样的,但就是出错。这个时候,就要仔细看看控制符和代码的问题。
要减少这类问题,在网页拷贝的代码, 先粘贴到一个纯文本的编辑器,例如 Notepad++ , 然后从 Notepad++ 选择和复制, 再粘贴到 VS 。
对于粘贴过来的代码,要特别注意其空格。例如, 下面这个就是从粘贴后的代码:
可以看到 第14行,18行 等的 空格特别长,当移动光标的时候,它是一个 空格!但实际上它并不是一个空格。一旦运行程序,就会提示记录记录为空,实际上是找不到 数据库文件,或 SQL语句错误等等。
处理的办法很简单, 就是在这些语句,手工逐个把空格删掉,然后按一下空格键加上空格。就可以发现自己加的空格位是比较小的,呵呵。
这些操作没有任何技术含量,但也值得分享一下,
C#操作SQLite方法实例详解
本文实例讲述了C#操作SQLite方法。分享给大家供大家参考。具体分析如下:
地址:
System.Data.Sqlite入手。。。
首先import/using:
Connection和Command:
1
2
|
private SQLiteConnection conn; private SQLiteCommand cmd; |
连接db:
1
2
|
conn = new SQLiteConnection( "Data Source=c:\test.db" ); conn.Open(); |
INSERT/UPDATE:
1
2
3
4
5
6
|
cmd = conn.CreateCommand(); cmd.CommandText = "INSERT INTO user(email,name) VALUES ('email','name')" ; cmd.ExecuteNonQuery(); cmd.CommandText = "UPDATE userSET name = 'Codelicious' WHERE ID = 1" ; cmd.ExecuteNonQuery(); |
SELECT:
1
2
3
4
5
6
7
8
9
10
|
cmd.CommandText = "SELECT ID, name FROM user" ; SQLiteDataReader reader = cmd.ExecuteReader(); if (reader.HasRows) { while (reader.Read()) { Console.WriteLine( "ID: " + reader.GetInt16(0)); Console.WriteLine( "name: " + reader.GetString(1)); } } |
模板程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
|
using System; using System.Data; using System.Data.Common; using System.Data.SQLite; namespace SQLiteQueryBrowser { /// <summary> /// 说明:这是一个针对System.Data.SQLite的数据库常规操作封装的通用类。 /// </summary> public class SQLiteDBHelper { private string connectionString = string .Empty; /// <summary> /// 构造函数 /// </summary> /// <param name="dbPath">SQLite数据库文件路径</param> public SQLiteDBHelper( string dbPath) { this .connectionString = "Data Source=" + dbPath; } /// <summary> /// 创建SQLite数据库文件 /// </summary> /// <param name="dbPath">要创建的SQLite数据库文件路径</param> public static void CreateDB( string dbPath) { using (SQLiteConnection connection = new SQLiteConnection( "Data Source=" + dbPath)) { connection.Open(); using (SQLiteCommand command = new SQLiteCommand(connection)) { command.CommandText = "CREATE TABLE Demo(id integer NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE)" ; command.ExecuteNonQuery(); command.CommandText = "DROP TABLE Demo" ; command.ExecuteNonQuery(); } } } /// <summary> /// 对SQLite数据库执行增删改操作,返回受影响的行数。 /// </summary> /// <param name="sql">要执行的增删改的SQL语句</param> /// <param name="parameters">执行增删改语句所需要的参数,参数必须以它们在SQL语句中的顺序为准</param> /// <returns></returns> public int ExecuteNonQuery( string sql, SQLiteParameter[] parameters) { int affectedRows = 0; using (SQLiteConnection connection = new SQLiteConnection(connectionString)) { connection.Open(); using (DbTransaction transaction = connection.BeginTransaction()) { using (SQLiteCommand command = new SQLiteCommand(connection)) { command.CommandText = sql; if (parameters != null ) { command.Parameters.AddRange(parameters); } affectedRows = command.ExecuteNonQuery(); } transaction.Commit(); } } return affectedRows; } /// <summary> /// 执行一个查询语句,返回一个关联的SQLiteDataReader实例 /// </summary> /// <param name="sql">要执行的查询语句</param> /// <param name="parameters">执行SQL查询语句所需要的参数,参数必须以它们在SQL语句中的顺序为准</param> /// <returns></returns> public SQLiteDataReader ExecuteReader( string sql, SQLiteParameter[] parameters) { SQLiteConnection connection = new SQLiteConnection(connectionString); SQLiteCommand command = new SQLiteCommand(sql, connection); if (parameters != null ) { command.Parameters.AddRange(parameters); } connection.Open(); return command.ExecuteReader(CommandBehavior.CloseConnection); } /// <summary> /// 执行一个查询语句,返回一个包含查询结果的DataTable /// </summary> /// <param name="sql">要执行的查询语句</param> /// <param name="parameters">执行SQL查询语句所需要的参数,参数必须以它们在SQL语句中的顺序为准</param> /// <returns></returns> public DataTable ExecuteDataTable( string sql, SQLiteParameter[] parameters) { using (SQLiteConnection connection = new SQLiteConnection(connectionString)) { using (SQLiteCommand command = new SQLiteCommand(sql, connection)) { if (parameters != null ) { command.Parameters.AddRange(parameters); } SQLiteDataAdapter adapter = new SQLiteDataAdapter(command); DataTable data = new DataTable(); adapter.Fill(data); return data; } } } /// <summary> /// 执行一个查询语句,返回查询结果的第一行第一列 /// </summary> /// <param name="sql">要执行的查询语句</param> /// <param name="parameters">执行SQL查询语句所需要的参数,参数必须以它们在SQL语句中的顺序为准</param> /// <returns></returns> public Object ExecuteScalar( string sql, SQLiteParameter[] parameters) { using (SQLiteConnection connection = new SQLiteConnection(connectionString)) { using (SQLiteCommand command = new SQLiteCommand(sql, connection)) { if (parameters != null ) { command.Parameters.AddRange(parameters); } SQLiteDataAdapter adapter = new SQLiteDataAdapter(command); DataTable data = new DataTable(); adapter.Fill(data); return data; } } } /// <summary> /// 查询数据库中的所有数据类型信息 /// </summary> /// <returns></returns> public DataTable GetSchema() { using (SQLiteConnection connection = new SQLiteConnection(connectionString)) { connection.Open(); DataTable data=connection.GetSchema( "TABLES" ); connection.Close(); //foreach (DataColumn column in data.Columns) //{ // Console.WriteLine(column.ColumnName); //} return data; } } } } |
完整的程序例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
|
using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Data.Common; using System.Data.SQLite; using SQLiteQueryBrowser; namespace SQLiteDemo { class Program { static void Main( string [] args) { //CreateTable(); //InsertData(); ShowData(); Console.ReadLine(); } public static void CreateTable() { string dbPath = "D:\Demo.db3" ; //如果不存在改数据库文件,则创建该数据库文件 if (!System.IO.File.Exists(dbPath)) { SQLiteDBHelper.CreateDB( "D:\Demo.db3" ); } SQLiteDBHelper db = new SQLiteDBHelper( "D:\Demo.db3" ); string sql = "CREATE TABLE Test3(id integer NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,Name char(3),TypeName varchar(50),addDate datetime,UpdateTime Date,Time time,Comments blob)" ; db.ExecuteNonQuery(sql, null ); } public static void InsertData() { string sql = "INSERT INTO Test3(Name,TypeName,addDate,UpdateTime,Time,Comments)values(@Name,@TypeName,@addDate,@UpdateTime,@Time,@Comments)" ; SQLiteDBHelper db = new SQLiteDBHelper( "D:\Demo.db3" ); for ( char c = "A" ; c <= "Z" ; c++) { for ( int i = 0; i < 100; i++) { SQLiteParameter[] parameters = new SQLiteParameter[]{ new SQLiteParameter( "@Name" ,c+i.ToString()), new SQLiteParameter( "@TypeName" ,c.ToString()), new SQLiteParameter( "@addDate" ,DateTime.Now), new SQLiteParameter( "@UpdateTime" ,DateTime.Now.Date), new SQLiteParameter( "@Time" ,DateTime.Now.ToShortTimeString()), new SQLiteParameter( "@Comments" , "Just a Test" +i) }; db.ExecuteNonQuery(sql, parameters); } } } public static void ShowData() { //查询从50条起的20条记录 string sql = "select * from test3 order by id desc limit 50 offset 20" ; SQLiteDBHelper db = new SQLiteDBHelper( "D:\Demo.db3" ); using (SQLiteDataReader reader = db.ExecuteReader(sql, null )) { while (reader.Read()) { Console.WriteLine( "ID:{0},TypeName{1}" , reader.GetInt64(0), reader.GetString(1)); } } } } } |
在实际情况中,采用通用类大批量插入数据会有些慢,这是因为在System.Data.SQLite中的操作如果没有指定操作,则会被当做一个事物,如果需要一次性写入大量记录,则建议显式创建一个事物,在这个事务中完成所有的操作比较好,这样的话比每次操作创建一个事物的效率要提升很多。
最终利用VS2008提供的功能,可以看到里面的数据如下:
需要说明的是在System.Data.SQLite中数据类型的规定不适很严格,从创建Test3表的SQL语句来看,表中addDate、UpdateTime、Time分别是DateTime、Date、Time类型字段,但实际上我们插入的时候没有按照这个规定,最终显示的结果也是尽量遵循数据库字段的定义。
总结
System.Data.SQLite确实是一个非常小巧精悍的数据库,作为对SQLite的封装(SQLite可以在Android等类型的手机上利用Java访问),它依然是体较小,同比性能高、内存消耗小、无需安装仅需一个dll就可以运行的优点(如果在Mobile手机上则需要两个文件),唯一的一个缺点是没有比较的GUI(图形用户界面),不过正因为如此它才得以体积小。
在实际开发中没有图形用户界面可能有些不便,我们可以使用VS来查看和操作数据,我自己也做了一个小东东,便于管理和维护数据,界面如下:
如果你要开发数据量在10万条以下的应用,我建议你尝试使用一下System.Data.SQLite,它或许是一个不错的选择。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
public static void CreateTable() { string dbPath = "D:\Demo.db3" ; //如果不存在改数据库文件,则创建该数据库文件 if (!System.IO.File.Exists(dbPath)) { SQLiteDBHelper.CreateDB( "D:\Demo.db3" ); } SQLiteDBHelper db = new SQLiteDBHelper( "D:\Demo.db3" ); string sql = "CREATE TABLE Test3(id integer NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,Name char(3),TypeName varchar(50),addDate datetime,UpdateTime Date,Time time,Comments blob)" ; db.ExecuteNonQuery(sql, null ); } public static void InsertData() { string sql = "INSERT INTO Test3(Name,TypeName,addDate,UpdateTime,Time,Comments)values(@Name,@TypeName,@addDate,@UpdateTime,@Time,@Comments)" ; SQLiteDBHelper db = new SQLiteDBHelper( "D:\Demo.db3" ); for ( char c = "A" ; c <= "Z" ; c++) { for ( int i = 0; i < 100; i++) { SQLiteParameter[] parameters = new SQLiteParameter[]{ new SQLiteParameter( "@Name" ,c+i.ToString()), new SQLiteParameter( "@TypeName" ,c.ToString()), new SQLiteParameter( "@addDate" ,DateTime.Now), new SQLiteParameter( "@UpdateTime" ,DateTime.Now.Date), new SQLiteParameter( "@Time" ,DateTime.Now.ToShortTimeString()), new SQLiteParameter( "@Comments" , "Just a Test" +i) }; db.ExecuteNonQuery(sql, parameters); } } } public static void ShowData() { //查询从50条起的20条记录 string sql = "select * from test3 order by id desc limit 50 offset 20" ; SQLiteDBHelper db = new SQLiteDBHelper( "D:\Demo.db3" ); using (SQLiteDataReader reader = db.ExecuteReader(sql, null )) { while (reader.Read()) { Console.WriteLine( "ID:{0},TypeName{1}" , reader.GetInt64(0), reader.GetString(1)); } } } |