开发软件的过程中,对于本地数据库的选择通常是 SQLite ,因为它的配置相对简单,并且不需要额外的数据库服务。SQLite 可以很好的支持关系型数据库所具备的一些基本特征,如标准 SQL 语法、事物、数据表和索引等,且占用资源较少,还可在移动设备上轻松使用。
此外,Entity Framework 的一些特性(如 Fluent API、Migration 等)可以让我们其非常方便的操作 SQLite ,并且,它的开发团队还在持续项目的迭代,这些方面都能够成为我们使用 EF Core 的原因。
使用过程
1.在创建好的 WPF 程序中安装 Entity Framework 和对 SQLite 的相关支持
// Entity Framework
Install-Package Microsoft.EntityFrameworkCore.Sqlite
// 提供了用于 Migration 的工具
Install-Package Microsoft.EntityFrameworkCore.Tools
2.创建数据库访问上下文
public class User
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { set; get; }
[MaxLength(50), Required]
public string Name { set; get; }
public string Age { set; get; }
public string Sex { get; set; }
}
public class LovePlayerContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=ZDY.LovePlayer.db");
}
public DbSet<User> User { set; get; }
}
3.生成数据迁移类文件
打开 Visual Studio 程序管理包控制台,输入:
Add-Migration Migration_001
首次运行时,程序将自动生成 Migrations 目录,并向 Migrations 目录下的项目添加以下三个文件:
- XXXXXXXXXXXXXX_Migration_001.cs - 主迁移文件 。 包含应用迁移所需的操作(在 Up() 中)和还原迁移所需的操作(在 Down() 中)。
- XXXXXXXXXXXXXX_Migration_001.Designer.cs - 迁移元数据文件 。 包含 EF 所用的信息。
- LovePlayerContextModelSnapshot.cs--当前模型的快照。 用于确定添加下一迁移时的更改内容。
其中,XXXXXXXXXXXXXX 为按执行时间生成的时间戳,文件名中的时间戳有助于保持文件按时间顺序排列,以便你可以查看更改进展。
当数据库模型发生改变时,需再次运行此命令生成新的 迁移。
4.在 WPF 项目中调用
App.xaml.cs
public App()
{
using (var db = new LovePlayerContext())
{
try
{
using (var context = new LovePlayerContext())
{
// 检查是否有新的迁移
if (context.Database.GetPendingMigrations().Any())
{
context.Database.Migrate(); //执行迁移
}
}
}
catch (NotSupportedException ex)
{
}
catch (Exception ex)
{
}
}
}
通过调用 context.Database.Migrate() 方法,将数据库结构同步至数据中,其中,当数据库文件不存在时,它将自动创建。
注意,请勿在 Migrate() 前调用 EnsureCreated()。 EnsureCreated() 会绕过迁移创建架构,这会导致 Migrate() 失败。
EnsureCreated() 与 Migrate() 的区别:EnsureCreated() 在数据库不存在的时候也会自动创建,但如果数据库存在且数据结构有更改时,之后的更改将不会更新到数据库中。
5.测试效果
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
using (var context = new LovePlayerContext())
{
if (context.User.ToList().Count == 0)
{
var cate1 = new User { Name = "User A" };
var cate2 = new User { Name = "User B" };
context.User.AddRange(cate1, cate2);
context.SaveChanges();
}
// 查询
var list = context.User.ToList();
this.DataList.ItemsSource = list;
}
}
}
MainWindow.xaml
<Grid>
<DataGrid x:Name="DataList" AutoGenerateColumns="True"></DataGrid>
</Grid>