完善 .Net Core 项目 — Entity Framework Core 入门 (ORM组件)

0. 写在前面

写这个系列文章的主要原因是,本人经常忘记自己之前折腾过的工具怎么使用。因此记录下这些工具的入门使用方法,旨在快速上手这些工具。

个人水平有限,如果有什么不对的地方,希望大家斧正~

EF Core 的内容实在是太多了,所以这篇就写写快速上手。具体问题的细节给出了官网教程的相应链接。以后有时间再每部分详细整理下。

Microsoft 的官方文档:Home

1. EF Core 简介

Entity Framework (EF) Core 是轻量化、可扩展和跨平台版的 Entity Framework 数据访问技术,支持 .NET 开发人员使用 .NET 对象处理数据库的对象关系映射程序 (O/RM)。 它将开发人员从编写大量 SQL 语句中解放出来。
关于 O/RM 个人理解的也不是很深,写写自己的理解。
没有使用 O/RM 时,如果开发人员想从数据库读取数据反序列化一个类的对象,需要以下步骤:

《完善 .Net Core 项目 — Entity Framework Core 入门 (ORM组件)》
《完善 .Net Core 项目 — Entity Framework Core 入门 (ORM组件)》 没有O/RM,开发人员需要承担从数据反序列化的责任

加入 O/RM 后,查询数据库的工作被交给 O/RM 框架。开发人员只需要访问 O/RM 的接口就可以得到反序列化的对象,

《完善 .Net Core 项目 — Entity Framework Core 入门 (ORM组件)》
《完善 .Net Core 项目 — Entity Framework Core 入门 (ORM组件)》 添加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 数据库配置

有两种方式对数据库进行配置:

class MyDBContext : DBContext
{
    ...
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"connectionString");
    }
}

3.3 .Net 对象与数据库实体关联

MyDBContext 的类中定义 DbSet 属性,把 .Net 对象与数据库中的实体进行关联。若 DbSet 属性有共有的 setter,则在类创建时会自动初始化。

class MyDBContext : DBContext
{
    public DbSet<MyModel> MyModels { get; set; }
}

4. EF Core 操作数据

4.1 创建模型

只要在 MyDBContext 添加 DbSet 类型的属性 BlogsBlog 及其包含的所有类型都会暴露给 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.PostsPost.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
  1. 安装 Microsoft.EntityFrameworkCore.Proxies
  2. 调用 UseLazyLoadingProxies 开启 Lazy loading 功能
  3. 启用 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 项目系列,请见:

        原文作者:尚海
        原文地址: https://zhuanlan.zhihu.com/p/35652195
        本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
    点赞