文章目录
- 1、前置环境
- 2、数据的建立
- 3、数据库的访问
- 4、验证与查看数据
- 5、常见问题
- 6、要点汇总
1、前置环境
安装 SQLite 软件包:点击工具栏工具>NuGet 包管理器>程序包管理器控制台:
在控制台输入下载命令:
Install-Package System.Data.SQLite.Core说明:
System.Data.SQLite.Core是 .NET Framework / WinForms 项目的首选包,安装后自动携带 32/64 位原生引擎SQLite.Interop.dll。- 也可以走「工具 > NuGet 包管理器 > 管理解决方案的 NuGet 程序包」图形界面搜索安装,效果相同。
- 不需要同时安装
Microsoft.Data.Sqlite、SQLitePCLRaw.*,两套驱动混装会导致无法加载 DLL"e_sqlite3"报错。
2、数据的建立
核心思路:SQLite 的"建库"就是创建一个文件,连接串指向的文件不存在时会自动创建;表结构用CREATE TABLE IF NOT EXISTS在程序启动时执行一次,重复运行不会报错也不会清数据。
具体步骤:
(1)新建一个类文件Db.cs,引入命名空间:
using System.Data.SQLite; using System.IO; using System.Windows.Forms; // 用到 Application.StartupPath(2)定义数据库文件路径与连接字符串:
// 数据库文件放在程序运行目录(bin\Debug)下 private static readonly string DbPath = Path.Combine(Application.StartupPath, "myapp.db"); private static readonly string ConnStr = "Data Source=" + DbPath + ";Version=3;";
Data Source指向.db文件路径;Version=3表示使用 SQLite 3 协议。
(3)封装获取连接的方法(用完即关,SQLite 连接开销极小):
public static SQLiteConnection GetConnection() { var conn = new SQLiteConnection(ConnStr); conn.Open(); return conn; }(4)编写初始化方法,执行建表 SQL:
public static void Init() { using (var conn = GetConnection()) using (var cmd = conn.CreateCommand()) { cmd.CommandText = @"CREATE TABLE IF NOT EXISTS ..."; cmd.ExecuteNonQuery(); } }(5)在程序入口最先调用一次Init()(Program.cs):
[STAThread] static void Main() { Db.Init(); // 建库 + 建表,必须放在窗体启动之前 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new For()); }(6)运行程序,`bin\Debug\` 目录下出现 `myapp.db`,建库完成。整体代码参考:
public static class Db { // 数据库文件放在程序目录下 private static readonly string DbPath = Path.Combine(Application.StartupPath, "myapp.db"); private static readonly string ConnStr = "Data Source=" + DbPath + ";Version=3;"; // 获取连接(每次操作用完即关,SQLite 开销很小) public static SQLiteConnection GetConnection() { var conn = new SQLiteConnection(ConnStr); conn.Open(); return conn; } // 程序启动时调用一次:建库 + 建表 public static void Init() { using (var conn = GetConnection()) using (var cmd = conn.CreateCommand()) { cmd.CommandText = @" CREATE TABLE IF NOT EXISTS Users ( Id INTEGER PRIMARY KEY AUTOINCREMENT, UserName TEXT NOT NULL UNIQUE, Password TEXT NOT NULL, Phone TEXT, CreatedAt TEXT DEFAULT (datetime('now','localtime')) ); CREATE TABLE IF NOT EXISTS Orders ( Id INTEGER PRIMARY KEY AUTOINCREMENT, UserId INTEGER NOT NULL, Amount REAL NOT NULL, Status TEXT DEFAULT '待处理', FOREIGN KEY (UserId) REFERENCES Users(Id) );"; cmd.ExecuteNonQuery(); } } }3、数据库的访问
固定套路:Db.GetConnection()拿连接 → 建Command→ 写 SQL(参数化)→ 执行 →using自动释放。
(1)查询:填充到 DataGridView
private void LoadUsers() { using (var conn = Db.GetConnection()) using (var da = new SQLiteDataAdapter( "SELECT Id AS 编号, UserName AS 用户名, Phone AS 电话, CreatedAt AS 创建时间 FROM Users ORDER BY Id", conn)) { var dt = new DataTable(); da.Fill(dt); // 执行查询并填充 dgvUsers.DataSource = dt; // 绑定显示 } }(2)插入:注意@参数占位,禁止字符串拼接
using (var conn = Db.GetConnection()) using (var cmd = conn.CreateCommand()) { cmd.CommandText = "INSERT INTO Users(UserName, Password, Phone) VALUES(@u, @p, @ph)"; cmd.Parameters.AddWithValue("@u", txtName.Text.Trim()); cmd.Parameters.AddWithValue("@p", "123456"); cmd.Parameters.AddWithValue("@ph", txtPhone.Text.Trim()); int rows = cmd.ExecuteNonQuery(); // 返回受影响行数 }(3)修改:
using (var conn = Db.GetConnection()) using (var cmd = conn.CreateCommand()) { cmd.CommandText = "UPDATE Users SET Phone=@ph WHERE Id=@id"; cmd.Parameters.AddWithValue("@ph", txtPhone.Text.Trim()); cmd.Parameters.AddWithValue("@id", id); cmd.ExecuteNonQuery(); }(4)删除:
using (var conn = Db.GetConnection()) using (var cmd = conn.CreateCommand()) { cmd.CommandText = "DELETE FROM Users WHERE Id=@id"; cmd.Parameters.AddWithValue("@id", id); cmd.ExecuteNonQuery(); }(5)查询单个值(登录校验、统计等):
using (var conn = Db.GetConnection()) using (var cmd = conn.CreateCommand()) { cmd.CommandText = "SELECT COUNT(*) FROM Users WHERE UserName=@u AND Password=@p"; cmd.Parameters.AddWithValue("@u", txtName.Text.Trim()); cmd.Parameters.AddWithValue("@p", txtPwd.Text.Trim()); long count = (long)cmd.ExecuteScalar(); // 返回第一行第一列 if (count > 0) MessageBox.Show("登录成功"); }三种执行方式的区别:
| 执行方法 | 适用场景 | 返回值 |
|---|---|---|
ExecuteNonQuery() | INSERT / UPDATE / DELETE、建表 | 受影响行数 |
ExecuteScalar() | COUNT / MAX / 取单个字段 | 第一行第一列(object,需强转) |
ExecuteReader()/SQLiteDataAdapter.Fill() | SELECT 多行多列 | 读取器 / DataTable |
4、验证与查看数据
.db文件不能用记事本或 Visual Studio 直接打开(是二进制文件,打开是乱码),需用专用工具:
- DB Browser for SQLite(免费开源,https://sqlitebrowser.org):打开
bin\Debug\myapp.db,「数据库结构」页看表、「浏览数据」页看记录。 - 查看前建议先关闭程序,避免 SQLite 文件锁导致
database is locked。
5、常见问题
(1)System.DllNotFoundException:无法加载 DLL"e_sqlite3"
原因是项目里混装了两套 SQLite 驱动,或原生 DLL 未复制到输出目录。处理:卸载全部 SQLite 相关包后只装一个。
Uninstall-PackageMicrosoft.Data.Sqlite-ForceUninstall-PackageSQLitePCLRaw.bundle_e_sqlite3-ForceUninstall-PackageSQLitePCLRaw.core-ForceInstall-PackageSystem.Data.SQLite.Core生成后确认bin\Debug\x86\SQLite.Interop.dll与bin\Debug\x64\SQLite.Interop.dll均存在。
(2)no such table: Users
Db.Init()没有被调用,或调用晚于查询。确认它在Program.Main()的第一行。
(3)database is locked
另一个进程(如 DB Browser)占用了文件,或连接未关闭。坚持用using包裹连接。
(4)数据被清空/表丢失
不要用CREATE TABLE(无IF NOT EXISTS)加DROP TABLE的组合做初始化;也不要把bin\Debug\myapp.db当作"临时文件"删除——它就是正式数据。
6、要点汇总
- SQLite 是嵌入式数据库,无需安装 SQL Server、MySQL 等数据库服务,NuGet 装包即可。
- 建库 = 建文件,连接串指向的
.db不存在时自动创建。 - 建表语句必须带
IF NOT EXISTS,保证程序重复启动安全。 - SQL 值一律用
@参数+AddWithValue,防注入、防单引号报错。 - 连接一律
using包裹,用完即关。 - 数据库文件随程序发布,拷到任何 Windows 电脑可直接运行,无需配环境。