# 模块二 基础巩固 EF Core 介绍

## 2.4.2 EF Core -- 介绍 <a href="#id-242efcore-jie-shao" id="id-242efcore-jie-shao"></a>

* ORM
* Repository 仓储
* UnitOfWork 工作单元
* DB Context 与 DB Set
* EF Core快速开始示例

### ORM <a href="#orm" id="orm"></a>

ORM：object-rational mapping

* 对 SQL 语言进行封装，降低使用难度，多种 SQL 语言的抽象
* 多出来的对事务、连接池、迁移、种子数据等一些功能
* 多数情况下 ORM 生成的 SQL 脚本比你自己写的要好

### Repository 仓储 <a href="#repository-cang-chu" id="repository-cang-chu"></a>

在领域层和数据映射层之间，像一个内存级别的领域对象集合

* 为领域业务的单元测试提供替换点
* 集中数据库访问逻辑

![](https://3083743005-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8gwpNo3eyzHkX0O40HRA%2Fuploads%2FDkJPSu4tWNIR0UWDgHHw%2F196.jpg?alt=media\&token=c6c4f6bc-a36b-4005-9b5f-a0d48daafa62)

### UnitOfWork 工作单元 <a href="#unitofwork-gong-zuo-dan-yuan" id="unitofwork-gong-zuo-dan-yuan"></a>

一个工作单元在一个事务范围内保留所有对数据库的变更，在这个工作单元结束的时候一次性提交所有改动到数据库

### DB Context 与 DB Set <a href="#dbcontext-yu-dbset" id="dbcontext-yu-dbset"></a>

DB Context（UnitOfWork 工作单元）

DB Set（Repository 仓储）

EF Core 提供一个 DB Context 和多个 DB Set 组合完成数据查询和更新操作的 ORM 框架

### EF Core快速开始示例 <a href="#efcore-kuai-su-kai-shi-shi-li" id="efcore-kuai-su-kai-shi-shi-li"></a>

* 创建一个空的 web api 项目
* 添加 Pomelo.EntityFrameworkCore.Mysql 的 nuget 包引用
* 创建实体
* 创建 DbContext
* 配置连接字符串并且注入 DbContext
* 使用 DbContext 完成数据查询与插入

#### 创建实体 <a href="#chuang-jian-shi-ti" id="chuang-jian-shi-ti"></a>

Entity

```
namespace LighterApi.Data
{
    public class Entity
    {
        /// <summary>
        /// 主键Id
        /// </summary>
        public string Id { get; set; }

        /// <summary>
        /// 全局唯一的身份
        /// </summary>
        public string IdentityId { get; set; }

        /// <summary>
        /// 租户Id
        /// </summary>
        public string TenantId { get; set; }

        /// <summary>
        /// 用户Id
        /// </summary>
        public string UserId { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreatedAt { get; set; }

        /// <summary>
        /// 创建的用户
        /// </summary>
        public string CreatedBy { get; set; }

        /// <summary>
        /// 最后修改时间
        /// </summary>
        public DateTime LastUpdateAt { get; set; }

        /// <summary>
        /// 最后修改人
        /// </summary>
        public string LastUpdateBy { get; set; }
    }
}
```

Assistant

```
namespace LighterApi.Data.Project
{
    public class Assistant : Entity
    {
        public string MemberId { get; set; }

        public string ProjectGroupId { get; set; }
    }
}
```

Project

```
namespace LighterApi.Data.Project
{
    public class Project : Entity
    {
        public string Title { get; set; }

        public DateTime StartDate { get; set; }

        public DateTime EndDate { get; set; }

        public string SupervisorId { get; set; }

        public string PlanId { get; set; }
    }
}
```

Member

```
namespace LighterApi.Data.Project
{
    public class Member : Entity
    {
        public int Progress { get; set; }

        public string ProjectId { get; set; }
    }
}
```

ProjectGroup

```
namespace LighterApi.Data.Project
{
    public class ProjectGroup : Entity
    {
        public string Name { get; set; }

        public string ProjectId { get; set; }
    }
}
```

Task

```
namespace LighterApi.Data.Project
{
    public class Task : Entity
    {
        public string Title { get; set; }

        public string SectionId { get; set; }

        public string Description { get; set; }

        public string ProjectId { get; set; }

        public string MemberId { get; set; }

        //public EnumTaskStauts Status { get; set; }
    }
}
```

EnumTaskStauts

```
namespace LighterApi.Share
{
    public class EnumTaskStauts
    {
    }
}
```

#### 创建 DbContext <a href="#chuang-jian-dbcontext" id="chuang-jian-dbcontext"></a>

LighterDbContext

```
namespace LighterApi.Data
{
    public class LighterDbContext : DbContext
    {
        public LighterDbContext(DbContextOptions<LighterDbContext> options) : base(options)
        {

        }

        public DbSet<Project.Project> Projects { get; set; }

        public DbSet<Project.Member> Members { get; set; }

        public DbSet<Project.Assistant> Assistants { get; set; }

        public DbSet<Project.ProjectGroup> ProjectGroups { get; set; }

        public DbSet<Project.Task> Tasks { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
        }
    }
}
```

#### 配置连接字符串并且注入 DbContext <a href="#pei-zhi-lian-jie-zi-fu-chuan-bing-qie-zhu-ru-dbcontext" id="pei-zhi-lian-jie-zi-fu-chuan-bing-qie-zhu-ru-dbcontext"></a>

需要将 server 地址修改为数据库服务器地址

appsettings.json

```
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "ConnectionStrings": {
    "LighterDbContext": "server=127.0.0.1;port=7306;user=root;password=root123456@;database=lighter"
  },
  "AllowedHosts": "*"
}
```

Startup

```
public IConfiguration Configuration { get; }

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}
```

```
services.AddDbContext<LighterDbContext>(options =>
{
    options.UseMySql(Configuration.GetConnectionString("LighterDbContext"));
});

services.AddControllers();
```

```
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});
```

#### 使用 DbContext 完成数据查询与插入 <a href="#shi-yong-dbcontext-wan-cheng-shu-ju-cha-xun-yu-cha-ru" id="shi-yong-dbcontext-wan-cheng-shu-ju-cha-xun-yu-cha-ru"></a>

初始化数据库 ，注意在初始化以前确保正确配置了连接字符串，并且在startup.cs中添加了DbContext的注入

```
// 安装dotnet tool ef工具 
dotnet tool install --global dotnet-ef

// 以下命令需要在api项目的目录下执行 
// 在项目内安装 
dotnet add package Microsoft.EntityFrameworkCore.Design

//添加迁移文件
dotnet ef migrations add Init

// 更新数据库 
dotnet ef database update
```

创建控制器 ProjectController

```
namespace LighterApi.Controller
{
    [ApiController]
    [Route("api/[controller]")]
    public class ProjectController : ControllerBase
    {
        private readonly LighterDbContext _lighterDbContext;

        public ProjectController(LighterDbContext lighterDbContext)
        {
            _lighterDbContext = lighterDbContext;
        }
    }
}
```

列表

```
[HttpGet]
public async Task<IEnumerable<Project>> GetListAsync(CancellationToken cancellationToken)
{
    return await _lighterDbContext.Projects.ToListAsync(cancellationToken);
}
```

新增

```
public async Task<ActionResult<Project>> CreateAsync([FromBody] Project project,
    CancellationToken cancellationToken)
{
    project.Id = Guid.NewGuid().ToString();
    _lighterDbContext.Projects.Add(project);
    await _lighterDbContext.SaveChangesAsync(cancellationToken);

    return StatusCode((int) HttpStatusCode.Created, project);
}
```

修改启动端口，launchSettings.json

```
"applicationUrl": "https://localhost:6001;http://localhost:6000",
```

为了简化日期格式入参，添加 nuget 包 Microsoft.AspNetCore.Mvc.NewtonsoftJson

```
services.AddControllers()
        .AddNewtonsoftJson();
```

在 Postman 中添加环境变量

![](https://3083743005-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8gwpNo3eyzHkX0O40HRA%2Fuploads%2FuhjWe3wJukGrA8Vny6OZ%2F197.jpg?alt=media\&token=43fe25e5-8d19-4444-b3e4-4c5944aeca50)

启动项目，访问新增，列表接口

![](https://3083743005-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8gwpNo3eyzHkX0O40HRA%2Fuploads%2FNxj78xlAekttfuSDSHZO%2F198.jpg?alt=media\&token=8936aab1-5ff9-4f59-a58c-e8b34ea6e1cb)

![](https://3083743005-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8gwpNo3eyzHkX0O40HRA%2Fuploads%2FVKF0z8HetHRZAifnmzJp%2F199.jpg?alt=media\&token=4eac905f-9fb3-4825-b64c-5d3476edceea)

### GitHub源码链接： <a href="#github-yuan-ma-lian-jie" id="github-yuan-ma-lian-jie"></a>

<https://github.com/MingsonZheng/ArchitectTrainingCamp/tree/main/LighterApi>
