0. 写在前面
写这个系列文章的主要原因是,本人经常忘记自己之前折腾过的工具怎么使用。因此记录下这些工具的入门使用方法,旨在快速上手这些工具。
个人水平有限,如果有什么不对的地方,希望大家斧正~
EF Core 的内容实在是太多了,所以这篇就写写快速上手。具体问题的细节给出了官网教程的相应链接。以后有时间再每部分详细整理下。
Microsoft 的官方文档:Home
1. EF Core 简介
Entity Framework (EF) Core 是轻量化、可扩展和跨平台版的 Entity Framework 数据访问技术,支持 .NET 开发人员使用 .NET 对象处理数据库的对象关系映射程序 (O/RM)。 它将开发人员从编写大量 SQL 语句中解放出来。
关于 O/RM 个人理解的也不是很深,写写自己的理解。
没有使用 O/RM 时,如果开发人员想从数据库读取数据反序列化一个类的对象,需要以下步骤:
没有O/RM,开发人员需要承担从数据反序列化的责任
加入 O/RM 后,查询数据库的工作被交给 O/RM 框架。开发人员只需要访问 O/RM 的接口就可以得到反序列化的对象,
添加O/RM框架,反序列化的工作交给框架负责
2. EF Core 安装
2.1 安装 EF Core 工具
EF Core 工具数据库逆向工程和管理数据库迁移的脚手架工具(看不懂…)。原话:
The Entity Framework Core Tools help you during the development of EF Core apps. They’re primarily used to scaffold a DbContext and entity types by reverse engineering the schema of a database, and to manage Migrations.
它有以下功能
- 查询
DbContext
的信息 - 列举可用
DbContext
- 创建
DbContext
和数据库实体的脚手架工作 - 新建 migration
- 列举可用 migration
- 删除最后一次 migration
- 从 migration 生成 SQL 脚本
- 更新数据库到指定 migration
- 删除数据库
migration 是指增量地将 EF Core 模型的变化同步到数据库中,并且保留原数据库的数据
2.1.1 安装 EF Core 命令行工具
EF Core 包含一套以 dotnet ef
开头的附加命令行工具,是 dotnet
命令行工具对扩展。如果使用 Visual Studio,建议 Package Manager Console (PMC) 工具,因为它提供了更多功能。
要使用 dotnet ef 命令行工具,需要执行以下步骤:
1. 编辑应用程序的 .csproj 文件,将 Microsoft.EntityFrameworkCore.Tools.DotNet
添加为 DotNetCliToolReference
项
2. 执行以下命令
~ $ dotnet add package Microsoft.EntityFrameworkCore.Design
~ $ dotnet restore
完成以上步骤,.csproj 文件如下所示:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design"
Version="2.0.0"
PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet"
Version="2.0.0" />
</ItemGroup>
</Project>
PackageReference
项中的 PrivateAssets="All"
表示它不暴露给引用该项目的其它项目,适用于仅在开发阶段使用的包。
EF Core CLI 工具使用方法详见:使用命令行工具
2.1.2 安装 EF Core 包管理器控制台工具
在 PMC 中运行以下命令
PM > Install-Package Microsoft.EntityFrameworkCore.Tools
通过如下命令可以测试安装是否成功,
PM > Get-Help about_EntityFrameworkCore
EF Core PMC 工具使用方法详见:使用包管理器控制台工具
2.2 安装 EF Core
EF Core 的安装与具体的数据库引擎有关,例如 Microsoft 官方教程中安装针对 SQL Server 的 Nuget 包方法如下,
- PMC 安装
PM > Install-Package Microsoft.EntityFrameworkCore.SqlServer
- CLI 安装
~ $ dotnet add package Microsoft.EntityFrameworkCore.SqlServer
以下列举一些常用的数据库引擎 Nuget 包的安装 (以 PMC 安装为例)
- MySQL
PM > Install-Package MySql.Data.EntityFrameworkCore
- SQLite
PM > Install-Package Microsoft.EntityFrameworkCore.Sqlite
- EF Core in-memory 数据库 (用于测试)
PM > Install-Package Microsoft.EntityFrameworkCore.InMemory
- MyCat Server
PM > Install-Package Pomelo.EntityFrameworkCore.MyCat
更多数据库支持:Database Providers
3. EF Core 使用概览
3.1 DBContext
简介
DbContext
表示与数据库的一次会话,EF Core 中「增删改查」操作都基于该类。DbContext
结合了 Unit Of Work 模式 和 Repository 模式。
一般情况下,需要创建继承于 DbContext
的自定义类 (本文中以 MyDbContext
为例),然后通过该类进行数据库操作。该类的角色类似于 DAL 。
3.2 数据库配置
有两种方式对数据库进行配置:
- 重写
DbContext.OnConfiguring(DbContextOptionsBuilder)
方法。以官网教程配置 SQL Server 为例
class MyDBContext : DBContext
{
...
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"connectionString");
}
}
- 通过
DbContextOptionsBuilder
类创建DbContextOptions
实例,并通过构造函数DbContext(DbContextOptions)
传递给DbContext
3.3 .Net 对象与数据库实体关联
在 MyDBContext
的类中定义 DbSet
属性,把 .Net 对象与数据库中的实体进行关联。若 DbSet
属性有共有的 setter
,则在类创建时会自动初始化。
class MyDBContext : DBContext
{
public DbSet<MyModel> MyModels { get; set; }
}
4. EF Core 操作数据
4.1 创建模型
只要在 MyDBContext
添加 DbSet
类型的属性 Blogs
,Blog
及其包含的所有类型都会暴露给 EF Core 。通过 MyDBContext
实例 myDBContext
的属性 myDBContext.Blogs
进行数据操作。
class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AuditEntry>();
}
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public Blog Blog { get; set; }
}
public class AuditEntry
{
public int AuditEntryId { get; set; }
public string Username { get; set; }
public string Action { get; set; }
}
上例中如下类型会被 EF Core 识别
- Blog :在属性 DbSet 中声明;
- Post :在 Blog 中涉及;
- AuditEntry :在 OnModelCreating 中声明。
⚠️ 上例中 Blog.Posts
和 Post.Blog
属性被称作导航属性 (Navigation Property) 。导航属性连接了数据库中的不同实体。
通过 EF Core 提供的功能,可以对模型进行更细致的操作。详见Creating a Model。
4.2 查询数据
利用 LINQ 对具体 Context
对象的 DbSet
属性进行查询操作即可。如,
using (var context = new MyDBContext())
{
var models = MyDBContext.MyModels
.Where(b => b.Id == "id")
.ToList();
}
对于包含导航属性的 .Net 对象,有三种加载导航属性的方式:
Eager loading
:进行查询的时候就加载导航属性的相关数据Explicit loading
:查询后某一时刻通过代码显式地从数据库加载相关数据Lazy loading
:仅当访问导航属性时,相关数据才会从数据库进行加载。加载由 EF Core 进行,无需额外操作。( EF Core 2.1 后可以使用 )
对于 Lazy loading
,有两种方式实现
- Simplest way
- 安装
Microsoft.EntityFrameworkCore.Proxies
包 - 调用
UseLazyLoadingProxies
开启Lazy loading
功能 - 启用
Lazy loading
的导航属性需要用virtual
关键词进行修饰,并且所在类必须是可被继承的。
ILazyLoader
服务或者 ILazyLoader.Load
方法的代理。详见 Lazy-loading without proxies 。4.5 保存数据
通过具体 Context
对象进行增、删、改操作,最后通过 context.SaveChanges();
方法将操作写入数据库。
using (var context = new MyBbContext())
{
var model = new MyModel();
context.MyModels.Add(model);
context.SaveChanges();
}
5. 单元测试
Microsoft 的官方文档给了两种测试 EF Core 的方法:
- 使用 SQLite 数据库的 in-memory 模式
- 使用 EF Core In-Memory 数据库
这里使用 EF Core In-Memory 方法为例,进行单元测试需要进行以下操作:
- 为了在生产环境和测试使用不同数据库,首先需要对原项目的
MyDBContext
类进行更改。目的是通过构造函数注入数据库引擎并阻止加载生产环境数据库引擎。具体有以下步骤: - 修改配置数据库处的逻辑
class MyDBContext : DBContext
{
...
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(@"connectionString");
}
}
}
- 实现带
DbContextOptions
参数的构造函数
public class MyDBContext : DbContext
{
public MyDBContext() { }
public MyDBContext(DbContextOptions<MyDBContext> options)
: base(options) { }
}
Microsoft.EntityFrameworkCore.InMemory
包,方法详见 2.2 安装 EF Core- 将 EF Core 的数据库配置为
In-Memory
。在测试项目中调用MyDBContext
时,新建Im-Memory
数据库配置,并通过构造函数在创建时注入该配置。
options = new DbContextOptionsBuilder<CholessContext>()
.UseInMemoryDatabase("choless")
.Options;
using (var context = new MyDBContext(options))
{
...
}
关于完善 .Net Core 项目系列,请见: