导读:本期聚焦于江户川创作的《C#如何使用System.Data.SQLite实现数据库连接与查询?完整操作指南》,敬请观看详情。为什么C#操作SQLite时推荐使用System.Data.SQLite而不是其他驱动?这篇文章从连接字符串的配置讲起,演示如何创建数据库文件、建立连接、执行增删改查操作,并深入讲解参数化查询防止SQL注入的原理。文中还对比了ExecuteNonQuery、ExecuteScalar和ExecuteReader三种执行方式的适用场景,分析了事务处理对批量写入性能的影响,最后给出连接池配置、资源释放和常见异常排查的实用技巧,帮你避开开发中的典型坑点。

System.Data.SQLite是SQLite官方推荐给.NET平台的ADO.NET提供程序,它完整实现了DbConnection、DbCommand、DbDataReader等抽象类,用法和SqlClient几乎一致。对于桌面小工具、本地缓存、嵌入式数据存储这类场景,SQLite配合System.Data.SQLite是非常省心的选择。本文将从环境搭建、连接管理、查询执行到事务优化,完整梳理这套库的核心用法。

C#如何使用System.Data.SQLite实现数据库连接与查询?完整操作指南

一、安装与环境准备

System.Data.SQLite可以通过NuGet直接安装。在Visual Studio的包管理控制台执行安装命令,或者在项目里右键管理NuGet包搜索安装都可以。需要注意的是,这个库有x86和x64两个原生依赖版本,如果程序目标平台配置不对,运行时会抛出无法加载 DLL SQLite.Interop.dll的经典异常。

// 包管理控制台执行
Install-Package System.Data.SQLite

// 或使用新的包引用格式
dotnet add package System.Data.SQLite

安装完成后,建议在项目属性中把目标平台设为Any CPU,并勾选首选32位或根据部署环境固定为x64。如果不慎出现Interop.dll加载失败,可手动把对应平台目录下的SQLite.Interop.dll复制到输出目录,这也是排查此类问题的第一手段。

命名空间引用很简单,代码文件顶部加上using System.Data.SQLite;即可。如果之前用过SqlClient,会发现接下来的所有操作都非常眼熟,这也是ADO.NET体系设计统一带来的好处。

二、建立连接与基础增删改查

连接SQLite的核心是构造正确的连接字符串。常用的属性包括Data Source(数据库文件路径)、Version(一般固定为3)、Pooling(是否启用连接池)。如果文件不存在,默认情况下打开连接时会自动创建一个新的数据库文件,这一点对初始化非常友好。

string connStr = "Data Source=mydb.db;Version=3;Pooling=true;";

using (var conn = new SQLiteConnection(connStr))
{
    conn.Open();

    // 创建表
    string createSql = @"CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        age INTEGER,
        create_time DATETIME DEFAULT CURRENT_TIMESTAMP)";

    using (var cmd = new SQLiteCommand(createSql, conn))
    {
        cmd.ExecuteNonQuery();
    }
}

执行操作时,三种方法各有分工。ExecuteNonQuery用于增删改和建表,返回受影响的行数;ExecuteScalar返回结果集第一行第一列的值,适合查总数、取最大值这类单值查询;ExecuteReader则返回一个流式读取器,适合遍历大量数据,读取过程中连接必须保持打开状态。

// 参数化插入,防止SQL注入
string insertSql = "INSERT INTO users (name, age) VALUES (@name, @age)";
using (var cmd = new SQLiteCommand(insertSql, conn))
{
    cmd.Parameters.AddWithValue("@name", "张三");
    cmd.Parameters.AddWithValue("@age", 28);
    int rows = cmd.ExecuteNonQuery();
}

// 查询单值
using (var cmd = new SQLiteCommand("SELECT COUNT(*) FROM users", conn))
{
    long count = (long)cmd.ExecuteScalar();
}

// 读取多行
using (var cmd = new SQLiteCommand("SELECT id, name, age FROM users WHERE age > @age", conn))
{
    cmd.Parameters.AddWithValue("@age", 20);
    using (var reader = cmd.ExecuteReader())
    {
        while (reader.Read())
        {
            Console.WriteLine($"{reader.GetInt32(0)} {reader.GetString(1)} {reader.GetInt32(2)}");
        }
    }
}

这里要特别强调参数化查询。拼接SQL字符串不仅容易被注入攻击,还会让SQLite每次都重新编译SQL语句。使用@参数名的形式传值,同一结构的SQL只会编译一次并缓存执行计划,批量操作时性能差距非常明显。

三、事务处理与性能优化

SQLite默认把每条INSERT语句当成一个独立事务,每次提交都会触发磁盘同步,这在循环插入几千条数据时会慢到难以接受。解决办法是用SQLiteTransaction把批量操作包在一个事务里,写入速度通常能提升几十倍甚至上百倍。

using (var conn = new SQLiteConnection(connStr))
{
    conn.Open();
    using (var tran = conn.BeginTransaction())
    {
        try
        {
            using (var cmd = new SQLiteCommand(
                "INSERT INTO users (name, age) VALUES (@name, @age)", conn, tran))
            {
                cmd.Parameters.Add("@name", DbType.String);
                cmd.Parameters.Add("@age", DbType.Int32);

                for (int i = 0; i < 10000; i++)
                {
                    cmd.Parameters[0].Value = $"用户{i}";
                    cmd.Parameters[1].Value = 20 + i % 40;
                    cmd.ExecuteNonQuery();
                }
            }
            tran.Commit();
        }
        catch
        {
            tran.Rollback();
            throw;
        }
    }
}

除了事务,还有几个配置项值得关注。连接字符串中加Journal Mode=WAL可以启用写前日志,让读写操作不再互相阻塞,多线程场景下收益很大;Synchronous=Normal能在性能和安全之间取得更好的平衡;启用Pooling=true可以复用物理连接,避免频繁打开关闭文件句柄的开销。

资源释放方面,务必用using语句包裹Connection、Command、DataReader和Transaction。SQLite连接底层持有非托管资源,单纯依赖垃圾回收可能导致文件一直被占用,出现database is locked异常时,第一步就应该检查是否有连接没有正确关闭。

四、常见异常与排查思路

开发中遇到的高频问题主要有三类。第一类是unable to open database file,多数是路径不存在、目录没有写权限或者相对路径指向了意料之外的位置,建议调试时打印Path.GetFullPath确认实际路径。第二类是database is locked,通常是多个连接同时写或者有Reader没关闭,启用WAL模式并保证及时释放资源能解决大部分情况。第三类是上面提到的SQLite.Interop.dll加载失败,属于平台配置问题。

另外提醒一点,SQLite对并发写的支持比较有限,它是文件级锁而不是行级锁。如果你的程序有多个线程频繁写入,建议用一个专门的队列把写操作串行化,或者考虑换用服务型数据库,不要硬扛锁冲突。

总的来说,System.Data.SQLite延续了ADO.NET的标准编程模型,学习成本几乎为零,配合事务和参数化查询,完全可以胜任本地数据存储的绝大多数需求。掌握连接字符串配置、三种执行方式的选择和事务包裹批量写入这几个要点,就能写出既快又稳的数据访问代码。

System.Data.SQLiteC#数据库连接SQLite查询修改时间:2026-09-09 13:38:47

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260909/53395.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。