Entity Framework Core

Entity Framework Core 是微软新一代的物件关联对应 (ORM) 框架，以 .NET Core 实作，不过它是归属于 ASP.NET Core 专案的一部分，在 ASP.NET Core 开始开发时就被列入标准功能，与现行的 Entity Framework 一样，是微软官方建议使用的资料存取功能，但 .NET Core 成功移植 ADO.NET 基础类别库 System.Data 之后，开发人员仍能使用 ADO.NET 作为资料存取的解决方案。

## 历史

2014年5月19日，微软决定为了让其.NET能跨平台，下一版Entity Framework将完全重写。2016年6月27日，发布了Entity Framework Core 1.0, 伴随着ASP.NET Core 1.0 和 .NET Core 1.0.本来其命名为Entity Framework 7，但为了突出其是完全重写而不是替换EF6所以重新命名。

Entity Framework Core 所有版本是完全独立的代码库，作为NuGet包提供。

Entity Framework Core 1.0使用Apache License v2 在 GitHub 开源。可运行于Windows, Linux和OSX。

2017年8月14日随Visual Studio 2017 15.3 和 ASP.NET Core 2.0 发布Entity Framework Core 2.0。

2019年9月23日随Visual Studio 2019 16.3 和 ASP.NET Core 3.0发布Entity Framework Core 3.0。

2019年12月3日发布了Entity Framework Core 3.1 (EF Core 3.1)并作为长期支持版本至少支持到2022年12月3日。

2021年1月12日发布了Entity Framework Core 5.0.2 (EF Core 5)。

2021年11月10日发布了Entity Framework Core 6.0 (EF Core 6)。

## 核心功能

Entity Framework Core 基本上以 ORM 架构为主，延续 Entity Framework 的作法发展，但 Entity Framework Core 不再支援 Database First 与 Model First 模式，而仅支援 Code First 模式，亦即使用程式码来处理 Model 以及数据库纲要对应的工作。

Entity Framework Core 1.0.0 目前支援下列功能：

- 数据库塑模 (Modeling)：使用 POCO 方式建立 Model 与其关联性、影子状态 (Shadow State) 属性维护、唯一性限制与索引、内建转换、模型验证、键值自动产生与关联-表格对应等。
- 变更追踪 (Change Tracking)：快照式变更追踪、存取已追踪的状态与附加已解除附加的资料项目或物件结构 (graph)。
- 储存功能 (Save Changes)：基本资料储存功能、乐观式锁定、异步变更储存、交易能力与批次处理。
- 查询 (Query)：基本 LINQ 的支援、混合式主从架构评估、关闭追踪功能、早期载入、异步查询、基本 BCL 函式的转换与 SQL 指令的执行。
- 数据库纲要管理 (Database Schema Management)：数据库建立与删除的 API 支援、数据库错误页面 (由 ASP.NET Core 提供) 与关联性数据库移转等。

目前正在实作中的有：

- 数据库塑模 (Modeling)：资料标记 (Entity Framework 时代的 Data Annotations) 与 TPH 继承模式。
- 分工的品质 (Cross-cutting quality)：文件、Intellisense 文件与 API 检阅。
- 效能 (Performance)：额外的效能覆盖与效能增进。
- 查询 (Query)：对关联属性的查询转换。
- 数据库的反向工程 (类似于 EF 的 Database First)。
- 稳定化对 Mac 与 Linux 的功能。
- 新的资料提供者。

在 1.0.0 内计划的功能有：

- 设计时期脉络 (context) 的发现与载入。
- 部署能力。
- 串联式删除。
- 记录功能。

## 资料提供者

Entity Framework Core 支援下列资料提供者：

- SQL Server
- SQLite
- In-Memory (内存内数据库)，可供不需要存取到关联性数据库的测试工作。
- PostgreSQL
- SQL Server Compact
- IBM 数据库服务器
- MySQL

## 开发方式

Entity Framework Core 的开发方式与原有 Entity Framework 不同的是，Entity Framework Core 不再支援以 UI 为主的数据库组态 (这是为了要适应 Linux 与 Mac 的开发环境)，且不论是何种模式 (Database First / Code First)，都是以程式码为主的环境对应，不再有 EDMX (Entity Framework Metadata) 存在，为达成这个目标，Entity Framework 提供了 Scaffold-Database 指令 (于 Package Management Console 中执行)，允许开发人员由数据库来产生 Model 的程式码。

```powershell
Scaffold-DbContext "'Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;''" Microsoft.EntityFrameworkCore.SqlServer
```

原本 Entity Framework 现有的资料模型同步指令 Add-Migration 与 Update-Database 在 Entity Framework Core 仍然支援，包含前述的 Scaffold-Database 指令，都被包装在 Microsoft.EntityFrameworkCore.Tools 套件内，可以由 Package Management Console 中执行 Install-Package 安装它，或是直接编辑 project.json 将它加入相依套件，然后再于 project.json 中加入工具的相关设定：

```json
  "tools": {
    "Microsoft.EntityFrameworkCore.Tools": {
      "version": "1.0.0-preview1-final",
      "imports": [
        "portable-net45+win8+dnxcore50",
        "portable-net45+win8"
      ]
    }
```

若是使用 Scaffold-Database 指令探测数据库时，除了 Model 会自动产生外，也会一并产生 DbContext 类别的衍生程式，作为连结数据库的入口，若是由新数据库，或是未使用 Scaffold-Database 指令的话，就要自行撰写这个类别。

```c#
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;

namespace EFGetStarted.AspNetCore.ExistingDb.Models
{
    public partial class BloggingContext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Blog>(entity =>
            {
                entity.Property(e => e.Url).IsRequired();
            });

            modelBuilder.Entity<Post>(entity =>
            {
                entity.HasOne(d => d.Blog)
                    .WithMany(p => p.Post)
                    .HasForeignKey(d => d.BlogId);
            });
        }

        public virtual DbSet<Blog> Blog { get; set; }
        public virtual DbSet<Post> Post { get; set; }
    }
}
```

就可以使用 DbContext 来操作数据库了，之后的部分就和 Entity Framework 差异不大。

若是 ASP.NET Core，则需再到 ASP.NET Core 的起始类别 (例如 Startup.cs)，将 Entity Framework Core 的 DbContext 加到 Dependency Injection 里面。

```c#
public void ConfigureServices(IServiceCollection services)
{
    var connection = @"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;";
    services.AddDbContext<BloggingContext>(options => options.UseSqlServer(connection));
    // ...
}
```

之后就可以由 Controller 取得这个 DbContext 进行资料存取的动作了，例如：

```c#
using EFGetStarted.AspNetCore.ExistingDb.Models;
using Microsoft.AspNetCore.Mvc;
using System.Linq;

namespace EFGetStarted.AspNetCore.ExistingDb.Controllers
{
    public class BlogsController : Controller
    {
        private BloggingContext _context;

        public BlogsController(BloggingContext context)
        {
            _context = context;
        }

        public IActionResult Index()
        {
            return View(_context.Blog.ToList());
        }

        public IActionResult Create()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Create(Blog blog)
        {
            if (ModelState.IsValid)
            {
                _context.Blog.Add(blog);
                _context.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(blog);
        }

    }
}
```

## 基本资料

- 作者：Microsoft
- 开发者：.NET Foundation and the open source community
- 类型：开放源代码、资料存取
- 许可协议：MIT license
- 编程语言：C#
- 网站： GitHub、文件库