平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“C#项目中添加本地数据库SQLite的干货教程”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。
结合项目来看,我们在日常开发工作中,不可避免地采用到数据库,这篇文章将介绍一个C# 轻量 ORM 库——SQLite.主要的概念介绍这里就不多说了,文章以干货为主。
1. 开发工具
Microsoft Visual Studio Community 2022 (64 位) - Current
版本 17.14.21 (November 2025)
2. 安装对应的 NuGet 包
结合项目来看,1)在 Visual Studio 中:右键项目 → 管理 NuGet 包;
2)搜索并安装:sqlite-net-pcl.
3. 建立文件夹
落到代码里,建议是新建文件夹,将有关数据库的内容保存在一起,这样便于管理,以下是我的文件结构,能够用来参考。

其中:DatabaseManager.cs存放的是数据库的管理操作;UserRepository.cs存放的是对User数据表的管理操作;User.cs存放的是User数据表的结构。
4. 建立数据表
从实现思路看,建立数据表的结构,也就是Model.以下是我的User.cs文件的内容,能够作为参考。
using SQLite;
namespace My.DatabaseModel
{
///
/// 用户表
///
[Table("User")]
public class User
{
[PrimaryKey, AutoIncrement]
[Column("id")]
public int Id { get; set; }
[Column("userId")]
public string DoctorId { get; set; }
[Column("avatar")]
public string Avatar { get; set; }
[Column("name")]
public string Name { get; set; }
}
}
落到代码里,1)其中 [PrimaryKey, AutoIncrement]表示id是该表的主键,数值自增。
落到代码里,2)userId建议保持唯一性,能够根据id变化,以下是参考,根据id修改后一定要记得更新。
// 1️ 插入 User
Db.Insert(user);
// 2️ 生成 PatientId
user.UserId= "U" + (10000 + user.Id);
// 3️ 更新 User
Db.Update(user);
5. 建立数据库
数据库的操作基本上是初始化和销毁两个操作而已。
using My.DatabaseModel;
using SQLite;
namespace My.Database
{
public class DatabaseManager
{
private static SQLiteConnection db;
private static string dbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "myDatabase.db");
public static SQLiteConnection DB
{
get
{
if (db == null)
{
Init();
}
return db;
}
}
public static void Init()
{
// 1 判断数据库是否存在
bool dbExists = File.Exists(dbPath);
// 2 创建连接
db = new SQLiteConnection(dbPath);
if (!dbExists)
{
Console.WriteLine("数据库不存在,创建数据库...");
// 自动创建表
// 用户表
db.CreateTable();
}
Console.WriteLine("数据库初始化完成");
}
///
/// 销毁数据库
///
public static void DestroyDatabase()
{
try
{
//1 关闭数据库连接
if (db != null)
{
db.Close();
db.Dispose();
db = null;
}
//2 删除数据库文件
if (File.Exists(dbPath))
{
File.Delete(dbPath);
Console.WriteLine("数据库已销毁");
}
}
catch (Exception ex)
{
Console.WriteLine("删除数据库失败: " + ex.Message);
}
}
///
/// 重置数据库
///
public static void ResetDatabase()
{
DestroyDatabase();
Init();
}
}
}
这里注意,销毁数据库时一定要先关闭数据库连接,再删除数据库文件。private static string dbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "myDatabase.db");就是新建数据库文件,文件名为“myDatabase.db”.文件名能够自定义的,建议根据自己的需求更换具有标识性的文件名,建议以Database结尾。
6. 增加对数据表的操作
结合项目来看,我将对数据表的操作以表为单位建立了文件——UserRepository.cs.以下是我的文件内容,能够作为参考。
using My.DatabaseModel;
using SQLite;
namespace RTLAB_MMDS.Database
{
public class UserRepository
{
private static SQLiteConnection Db => DatabaseManager.DB;
///
/// 插入数据
///
///
///
public User InsertUser(User user)
{
Db.Insert(user);
return user;
}
///
/// 获取全部数据
///
///
public ListGetAllUsers()
{
return Db.Table().ToList();
}
///
/// 根据用户id获取数据
///
///
///
public User GetUserByUserId(string userId)
{
return Db.Table()
.FirstOrDefault(d => d.UserId== userId);
}
///
/// 根据用户id删除患者
///
///
public void Delete(string userId)
{
Db.Table()
.Delete(d => d.UserId== userId);
}
///
/// 更新用户
///
public User Update(User user)
{
Db.Update(user);
return user;
}
}
}
在这个场景下,这种不涉及外键连接和多表组合的数据库操作是比较轻松的,这里写的也不是很全,但是基本逻辑是这样的,相对复杂的等会放后面单独讲。
实际处理时,还有一个点需留意的是我基本上每一个都写了return,实际根据项目情况写就好,我这里是为了下面的操作示例写的而已。
7. 数据表的操作示例
下面就给一个轻松的用户表增删改的操作示例。
private void example()
{
//初始化数据库
DatabaseManager.Init();
UserRepository repo = new UserRepository();
//创建用户
User user1= new User
{
UserId = "123",
Avatar = "",
Name = "张三",
};
//插入
user1 = repo.InsertUser(user1);
Console.WriteLine("创建用户成功:" + user1.Name);
// 查找
User user2 = repo.GetUserByUserId(user1.UserId);
Console.WriteLine("查找用户成功:" + user2.Name);
// 修改
user2.Name = "李四";
User user3 = repo.Update(user2);
Console.WriteLine("修改用户成功:" + user3.Name);
// 删除
repo.Delete(user3);
Console.WriteLine("删除用户成功");
}
理解这一步时,一定要初始化数据库,否则一切操作白搭,建议在Program.cs文件中就初始化。
从实现思路看,好了,以上的基本内容就讲完了。每次总结的时候都觉得当初摸索的自己像个傻子,囧。
下面说一下组合表的事情吧。
落到代码里,数据库通常不会只有像上面User这样轻松的表,一般可能还得存点别的结构,而在C#中又不给直接存什么List,还有数据比较大的情况下都存一张表检索又影响效率,所以,下面说一下组合的情况。
也是直接借助例子来讲解。
8. 组合表的结构
using SQLite;
namespace My.DatabaseModel
{
///
/// 患者表
///
[Table("User")]
public class User
{
[PrimaryKey, AutoIncrement]
[Column("id")]
public int Id { get; set; }
[Column("userId")]
public string DoctorId { get; set; }
[Column("avatar")]
public string Avatar { get; set; }
[Column("name")]
public string Name { get; set; }
[Ignore] // SQLite-Net 属性,告诉它不要映射到表
public ListOthers{ get; set; } = new List ();
}
///
/// 其他
///
[Table("Other")]
public class Other
{
[PrimaryKey, AutoIncrement]
[Column("id")]
public int Id { get; set; }
[Column("userId")]
public string UserId { get; set; }
[Column("otherName")]
public string OtherName { get; set; }
}
}
理解这一步时,1)Other也需在初始化数据库时新建表,即在DatabaseManager.cs中添加db.CreateTable
结合项目来看,2)Other.UserId=User.userId,当然字段名是能够自定义的,不过建议相同,这样可读性比较高。
3)List我这里存的是List,也能够存一条public Other OtherSingle{ get; set; } = new Other();如果存的OtherSingle,记得修改以下对组合表的操作。
9. 对组合表的操作
直接上代码吧,直观很重要!!!
using My.DatabaseModel;
using SQLite;
namespace RTLAB_MMDS.Database
{
public class UserRepository
{
private static SQLiteConnection Db => DatabaseManager.DB;
///
/// 插入数据
///
///
///
public User InsertUser(User user)
{
// RunInTransaction是保证数据库操作的原子性
// 通俗解释就是RunInTransaction里面的代码只有两个结果,全部失败和全部成功
Db.RunInTransaction(() =>
{
// 插入user
Db.Insert(user);
string userId = user.UserId;
if(user.others != null)
{
foreach(var other in user.Others)
{
other.UserId = userId;
// 插入other
Db.Insert(other);
}
}
});
return user;
}
///
/// 获取全部数据
///
///
public ListGetAllUsers()
{
var users = Db.Table().ToList();
// 把 Other 表按 UserId 分组,生成一个可以快速查找的内存索引
var otherLookup = Db.Table()
.ToList()
.ToLookup(p => p.UserId);
foreach(var user in users)
{
// 这里就可以根据user.userId直接索引到全部数据啦
user.Others = otherLookup[user.userId].ToList();
}
return users;
}
///
/// 根据用户id获取数据
///
///
///
public User GetUserByUserId(string userId)
{
var user = Db.Table()
.FirstOrDefault(d => d.UserId== userId);
if (user == null)
return null;
user.Others= Db.Table()
.Where(p => p.UserId == userId)
.ToList();
return user;
}
///
/// 根据用户id删除患者
///
///
public void Delete(string userId)
{
// 先删除子表里的数据
Db.Table()
.Delete(a => a.UserId == userId);
// 再删除主表里的数据
Db.Table()
.Delete(d => d.UserId== userId);
}
///
/// 更新用户
///
public User Update(User user)
{
Db.Update(user);
string userId = user.UserId;
// 删除旧Other
Db.Table()
.Delete(p => p.userId == userId);
// 插入新Other
if (user.Others != null)
{
foreach (var other in user.Others)
{
other.UserId = userId;
Db.Insert(other);
}
}
return user;
}
}
}
10. 插入组合表
这里就轻松给一个插入的示例吧,其他操作都是相通的。
private void example()
{
//初始化数据库
DatabaseManager.Init();
UserRepository repo = new UserRepository();
//创建用户
User user= new User
{
UserId = "123",
Avatar = "",
Name = "张三",
};
Listothers = new List ();
for(int i =0; i++; i<10)
{
Other other = new Other();
other.OtherName = $"OtherName_{i}";
others.Add(other);
}
user.Other = others;
//插入
user= repo.InsertUser(user);
Console.WriteLine("创建用户成功:" + user.Name);
}
11. 结语
落到代码里,总结就是,啥也不会的时候开头最难,等回顾的时候发现好像也就那样。数据库从无到有大致就是这样了。数据量大的情况下,比如存了绘图数据,有N个点的那种,也能够考虑文件存储方式,List也能够考虑json存储,这就下次遇到再说吧。感谢你看完全文!比心!
理解这一步时,总的来说,c#连接本地数据库适合结合实际项目边做边理解。先抓住核心思路,再逐步补上细节和边界处理,最后效果会更稳定,也更容易复用。

