SQLite 提供可靠的轻型数据库解决方案,用于在 Windows 应用中本地存储数据。 与传统需要单独服务器安装和复杂配置的数据库系统不同,SQLite 完全在应用程序进程中运行,并将数据存储在用户设备上的单个文件中。
本教程介绍如何使用Microsoft推荐的数据访问库将 SQLite 集成到 WinUI 应用程序中。 你将了解如何设置数据库、创建表并实现基本数据作,同时遵循安全最佳做法来防范常见漏洞。
你要完成的操作
在本教程中,你将学习如何:
- 将 Windows 应用配置为将 SQLite 与 Microsoft.Data.SQLite 库配合使用
- 创建和初始化本地数据库
- 实现安全的数据插入和检索方法
- 构建简单的用户界面以与数据交互
先决条件
若要完成本教程,需要:
- 使用“WinUI 应用程序开发”工作负载的 Visual Studio 2022 或更高版本
- 基本熟悉 C# 和 XAML
- 了解基本数据库概念
此方法提供的关键改进
在 Windows 应用中将 SQLite 用于本地数据存储具有以下优势:
- 简化部署:无需单独的数据库服务器安装
- 增强安全性:数据保留在用户的设备上本地
- 提高了性能:直接文件访问消除了网络延迟
- 降低复杂性:单文件数据库简化了备份和迁移
你将了解的技术适用于需要在本地存储结构化数据的任何 Windows 应用,从简单的设置存储到复杂的数据管理方案。
小窍门
可以使用 AI 帮助来帮助 避免 SQLite 中的 SQL 注入攻击。
SQLite 适用于本地存储的优势
✔️ SQLite 具有轻量和独立的特点。 它是没有其他任何依赖项的代码库。 无需进行任何配置。
✔️ 没有数据库服务器。 客户端和服务器在同一进程中运行。
✔️ SQLite 位于公共域中,因此你可以自由地使用它并将它与应用一起分配。
✔️ SQLite 可跨平台和体系结构工作。
可在此处了解有关 SQLite 的详细信息。
选择抽象层
我们建议使用由 Microsoft 构建的 Entity Framework Core 或开源 SQLite 库。
Entity Framework Core
Entity Framework (EF) 是一个对象关系映射程序,可用于使用特定于域的对象处理关系数据。 如果已使用此框架处理其他 .NET 应用中的数据,则可以在 WinUI 应用中使用相同的代码,并且它将处理对连接字符串的相应更改。
若要试用,请参阅 EF Core 入门。
SQLite 库
Microsoft.Data.Sqlite 库可在 System.Data.Common 命名空间中实现接口。 Microsoft 将主动保留这些实现,它们提供了围绕低级别本机 SQLite API 的直观的包装器。
本指南的其余部分将帮助你使用此库。
设置解决方案以使用 Microsoft.Data.SQLite 库
我们将从基本的 WinUI 项目开始,然后安装 SQLite NuGet 包。 有关如何创建第 一个 WinUI 项目的说明,请参阅“创建 WinUI 应用 ”。
所有受支持的 Windows 版本都支持 SQLite,因此你的应用无需将 SQLite 库打包。 相反,应用可以使用随 Windows 一起安装的 SQLite 版本。 这将带来几个方面的好处。
✔️ 减小了应用程序的大小,因为你不必下载 SQLite 二进制文件然后将其打包为应用程序的一部分。
✔️ 如果 SQLite 发布了针对 SQLite 中的 bug 和安全漏洞的重要修复程序,你就不必向用户推送你的应用的新版本。 Windows 版本的 SQLite 由 Microsoft 与 SQLite.org 协作维护。
✔️ 应用加载时间可能更短,因为 SDK 版本的 SQLite 很有可能已被加载到内存中。
首先向名为 DataAccess 的项目添加一个类。 如果计划与其他客户端代码共享数据访问逻辑,可使用 .NET 类库项目来包含数据访问代码,但我们不会在本示例中使用该类库。
右键单击该解决方法,然后单击“管理解决方案的 NuGet 包”。
此时,你已经有一个选择。 你可以使用 Windows 附带的 SQLite 版本,如果你出于某种原因要使用特定版本的 SQLite,则可以在程序中包含 SQLite 库。 我们将使用 Windows 附带的 SQLite 版本。
选择“浏览”选项卡,搜索“Microsoft.Data.SQLite”包,然后安装最新稳定版。
在 SQLite 数据库中添加和检索数据
我们将执行以下操作:
1️⃣ 准备数据访问类。
2️⃣ 初始化 SQLite 数据库。
3️⃣ 将数据插入到 SQLite 数据库。
4️⃣ 从 SQLite 数据库检索数据。
5️⃣ 添加基本用户界面。
准备数据访问类
在项目中打开 DataAccess 类并将其设为静态。
注意
虽然本示例会将数据访问代码置于静态类中,但这是一个设计选择,是完全可选的。
public static class DataAccess
{
}
将以下 using 语句添加到此文件顶部。
using Microsoft.Data.Sqlite;
using System.Collections.Generic;
初始化 SQLite 数据库
向 DataAccess 类添加一个初始化 SQLite 数据库的方法。
public async static void InitializeDatabase()
{
await ApplicationData.Current.LocalFolder
.CreateFileAsync("sqliteSample.db", CreationCollisionOption.OpenIfExists);
string dbpath = Path.Combine(ApplicationData.Current.LocalFolder.Path,
"sqliteSample.db");
using (var db = new SqliteConnection($"Filename={dbpath}"))
{
db.Open();
string tableCommand = "CREATE TABLE IF NOT " +
"EXISTS MyTable (Primary_Key INTEGER PRIMARY KEY, " +
"Text_Entry NVARCHAR(2048) NULL)";
var createTable = new SqliteCommand(tableCommand, db);
createTable.ExecuteReader();
}
}
此代码将创建 SQLite 数据库并将其存储在应用程序的本地数据存储区中。
在此示例中,我们将数据库命名为 sqlliteSample.db,但你可以使用任何想要的名称,只要你在你实例化的所有 SqliteConnection 对象中使用该名称。 在生产应用程序中,连接信息(如数据库文件名)应存储在应用配置中,而不是进行硬编码(请参阅使用 Visual Studio Connected Services 添加 Azure 应用配置)。
在项目的 App.xaml.cs 文件的构造函数中,调用 InitializeDatabase 类的 DataAccess 方法。 这将确保每次应用启动时都创建或打开数据库。
public App()
{
this.InitializeComponent();
DataAccess.InitializeDatabase();
}
将数据插入到 SQLite 数据库
向 DataAccess 类添加一个将数据插入到 SQLite 数据库的方法。 此代码在查询中使用参数以阻止 SQL 注入攻击。
public static void AddData(string inputText)
{
string dbpath = Path.Combine(ApplicationData.Current.LocalFolder.Path,
"sqliteSample.db");
using (var db = new SqliteConnection($"Filename={dbpath}"))
{
db.Open();
var insertCommand = new SqliteCommand();
insertCommand.Connection = db;
// Use parameterized query to prevent SQL injection attacks
insertCommand.CommandText = "INSERT INTO MyTable VALUES (NULL, @Entry);";
insertCommand.Parameters.AddWithValue("@Entry", inputText);
insertCommand.ExecuteReader();
}
}
从 SQLite 数据库检索数据
添加从 SQLite 数据库的表中获取所有数据行的方法。
public static List<string> GetData()
{
var entries = new List<string>();
string dbpath = Path.Combine(ApplicationData.Current.LocalFolder.Path,
"sqliteSample.db");
using (var db = new SqliteConnection($"Filename={dbpath}"))
{
db.Open();
var selectCommand = new SqliteCommand
("SELECT Text_Entry from MyTable", db);
SqliteDataReader query = selectCommand.ExecuteReader();
while (query.Read())
{
entries.Add(query.GetString(0));
}
}
return entries;
}
Read 方法将向前浏览返回的数据的行。 如果有剩下的行,它将返回 true,否则返回 false。
GetString 方法返回字符串形式的指定列的值。 它将接受一个整数值,该值表示所需的数据的从零开始的列序号。 你可以使用类似的方法,例如 GetDataTime 和 GetBoolean。 请根据列包含的数据的类型选择方法。
在此例子中,序号参数并不重要,因为我们选择了单个列中的所有条目。 但是,如果多个列是你的查询的一部分,请使用序号值获取你要从中拉取数据的列。
添加基本用户界面
在项目的 MainWindow.xaml 文件中,添加以下 XAML。
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<TextBox x:Name="Input_Box"/>
<Button Click="AddData">Add</Button>
<ListView x:Name="Output">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Grid>
此基本用户界面为用户提供了 TextBox,可用于键入我们将添加到 SQLite 数据库的字符串。 我们要将此 UI 中的 Button 连接到事件处理程序,后者将从 SQLite 数据库检索数据然后在 ListView 中显示数据。
在 MainWindow.xaml.cs 文件中,添加以下处理程序。 这是我们关联到 UI 中的 Click 的 Button 事件的方法。
private void AddData(object sender, RoutedEventArgs e)
{
DataAccess.AddData(Input_Box.Text);
Output.ItemsSource = DataAccess.GetData();
}
我们还需要确保在应用程序启动时加载所有现有数据。 向 MainWindow 构造函数添加一行代码以调用 GetData()。
public MainWindow()
{
this.InitializeComponent();
Output.ItemsSource = DataAccess.GetData();
}
完成了。 探索 Microsoft.Data.Sqlite 以了解 SQLite 数据库的其他功能。 查看下面的链接,了解在 Windows 应用中使用数据的其他方法。
避免 SQL 注入攻击
此示例中的代码使用参数化查询来防止 SQL 注入攻击。 切勿将用户输入连接到 SQL 查询字符串中。 始终使用参数。 可以向 Copilot 询问有关避免 SQL 注入攻击的更多提示。
以下文本显示了 Copilot 的示例提示:
Can you provide some best practices to avoid SQL injection attacks when writing SQLite queries in C# code?
Copilot 由 AI 提供支持,因此可能会带来意外和错误。 有关详细信息,请参阅 Copilot 常见问题解答。
相关内容
将你的应用直接连接到 SQL Server 数据库
请参阅在 Windows 应用中使用 SQL Server 数据库。
在跨不同平台的不同应用之间共享代码
使用 Azure SQL 后端添加大纲/细节页面
参阅客户订单数据库示例。