目录
- [参考文章](#参考文章) - [REST](#rest) - [常用http动词](#常用http动词) - [WebApi 在 Asp.NetCore 中的实现](#webapi-在-aspnetcore-中的实现) - [创建WebApi项目.](#创建webapi项目) - [集成Entity Framework Core操作Mysql](#集成entity-framework-core操作mysql) - [安装相关的包(为Xxxx.Infrastructure项目安装)](#安装相关的包为xxxxinfrastructure项目安装) - [建立Entity和Context](#建立entity和context) - [ConfigureService中注入EF服务](#configureservice中注入ef服务) - [迁移数据库](#迁移数据库) - [迁移数据库失败, 提示 `Unable to create an object of type '参考文章
REST
REST : 具象状态传输(Representational State Transfer,简称REST),是Roy Thomas Fielding博士于2000年在他的博士论文 "Architectural Styles and the Design of Network-based Software Architectures" 中提出来的一种万维网软件架构风格。
目前在三种主流的Web服务实现方案中,因为REST模式与复杂的SOAP和XML-RPC相比更加简洁,越来越多的web服务开始采用REST风格设计和实现。例如,Amazon.com提供接近REST风格的Web服务执行图书查询;
符合REST设计风格的Web API称为RESTful API。它从以下三个方面资源进行定义:
- 直观简短的资源地址:URI,比如:http://example.com/resources/ .
- 传输的资源:Web服务接受与返回的互联网媒体类型,比如:JSON,XML,YAML等...
- 对资源的操作:Web服务在该资源上所支持的一系列请求方法(比如:POST,GET,PUT或DELETE).
PUT和DELETE方法是幂等方法.GET方法是安全方法(不会对服务器端有修改,因此当然也是幂等的).
ps 关于幂等方法 :
看这篇 理解HTTP幂等性.
简单说,客户端多次请求服务端返回的结果都相同,那么就说这个操作是幂等的.(个人理解,详细的看上面给的文章)
不像基于SOAP的Web服务,RESTful Web服务并没有“正式”的标准。这是因为REST是一种架构,而SOAP只是一个协议。虽然REST不是一个标准,但大部分RESTful Web服务实现会使用HTTP、URI、JSON和XML等各种标准。
常用http动词
括号中是相应的SQL命令.
- GET(SELECT) : 从服务器取出资源(一项或多项).
- POST(CREATE) : 在服务器新建一个资源.
- PUT(UPDATE) : 在服务器更新资源(客户端提供改变后的完整资源).
- PATCH(UPDATE) : 在服务器更新资源(客户端提供改变的属性).
- DELETE(DELETE) : 在服务器删除资源.
WebApi 在 Asp.NetCore 中的实现
这里以用户增删改查为例.
创建WebApi项目.
参考ASP.NET Core WebAPI 开发-新建WebAPI项目.
注意,本文建立的Asp.NetCore WebApi项目选择.net core版本是2.2,不建议使用其他版本,2.1版本下会遇到依赖文件冲突问题!所以一定要选择2.2版本的.net core.
集成Entity Framework Core操作Mysql
安装相关的包(为Xxxx.Infrastructure项目安装)
- Microsoft.EntityFrameworkCore.Design
- Pomelo.EntityFrameworkCore.MySql
这里注意一下,Mysql官方的包是 MySql.Data.EntityFrameworkCore
,但是这个包有bug,我在github上看到有人说有替代方案 - Pomelo.EntityFrameworkCore.MySql
,经过尝试,后者比前者好用.所有这里就选择后者了.使用前者的话可能会导致数据库迁移失败(Update的时候).
PS: Mysql文档原文:
Install the MySql.Data.EntityFrameworkCore NuGet package.
For EF Core 1.1 only: If you plan to scaffold a database, install the MySql.Data.EntityFrameworkCore.Design NuGet package as well.EFCore - MySql文档
Mysql版本要求:
Mysql版本要高于5.7
使用最新版本的Mysql Connector(2019 6/27 目前是8.x).为Xxxx.Infrastructure项目安装EFCore相关的包:
为Xxxx.Api项目安装 Pomelo.EntityFrameworkCore.MySql
建立Entity和Context
ApiUser
```CSharp namespace ApiStudy.Core.Entities { using System; public class ApiUser { public Guid Guid { get; set; } public string Name { get; set; } public string Passwd { get; set; } public DateTime RegistrationDate { get; set; } public DateTime Birth { get; set; } public string ProfilePhotoUrl { get; set; } public string PhoneNumber { get; set; } public string Email { get; set; } } } ```UserContext
```CSharp namespace ApiStudy.Infrastructure.Database { using ApiStudy.Core.Entities; using Microsoft.EntityFrameworkCore; public class UserContext:DbContext { public UserContext(DbContextOptionsConfigureService中注入EF服务
services.AddDbContext<UserContext>(options =>
{
string connString = "Server=Xxx:xxx:xxx:xxx;Database=Xxxx;Uid=root;Pwd=Xxxxx; ";
options.UseMySQL(connString);
});
迁移数据库
- 在Tools > NuGet Package Manager > Package Manager Console输入命令.
- Add-Migration Xxx 添加迁移.
PS : 如果迁移不想要,使用 Remove-Migration 命令删除迁移. - Update-Database 更新到数据库.
迁移数据库失败, 提示 Unable to create an object of type '<Xxxx>Context'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
原因应该是EfCore迁移工具不知道如何创建 DbContext
导致的.
解决方案
在DbContext
所在的项目下新建一个类:
/// <summary>
/// 设计时DbContext的创建, 告诉EF Core迁移工具如何创建DbContext
/// </summary>
public class <Xxxx>ContextFactory : IDesignTimeDbContextFactory<<Xxxx>Context>
{
public <Xxxx>Context CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<<Xxxx>Context>();
optionsBuilder.UseMySql(
@"Server=[服务器ip];Database=[数据库]];Uid=[用户名];Pwd=[密码];");
return new <Xxxx>Context(optionsBuilder.Options);
}
}
数据库迁移结果
为数据库创建种子数据
-
写一个创建种子数据的类
UserContextSeed
namespace ApiStudy.Infrastructure.Database { using ApiStudy.Core.Entities; using Microsoft.Extensions.Logging; using System; using System.Linq; using System.Threading.Tasks; public class UserContextSeed { public static async Task SeedAsync(UserContext context,ILoggerFactory loggerFactory) { try { if (!context.ApiUsers.Any()) { context.ApiUsers.AddRange( new ApiUser { Guid = Guid.NewGuid(), Name = "la", Birth = new DateTime(1998, 11, 29), RegistrationDate = new DateTime(2019, 6, 28), Passwd = "123587", ProfilePhotoUrl = "https://www.laggage.top/", PhoneNumber = "10086", Email = "yu@outlook.com" }, new ApiUser { Guid = Guid.NewGuid(), Name = "David", Birth = new DateTime(1995, 8, 29), RegistrationDate = new DateTime(2019, 3, 28), Passwd = "awt87495987", ProfilePhotoUrl = "https://www.laggage.top/", PhoneNumber = "1008611", Email = "David@outlook.com" }, new ApiUser { Guid = Guid.NewGuid(), Name = "David", Birth = new DateTime(2001, 8, 19), RegistrationDate = new DateTime(2019, 4, 25), Passwd = "awt87495987", ProfilePhotoUrl = "https://www.laggage.top/", PhoneNumber = "1008611", Email = "David@outlook.com" }, new ApiUser { Guid = Guid.NewGuid(), Name = "Linus", Birth = new DateTime(1999, 10, 26), RegistrationDate = new DateTime(2018, 2, 8), Passwd = "awt87495987", ProfilePhotoUrl = "https://www.laggage.top/", PhoneNumber = "17084759987", Email = "Linus@outlook.com" }, new ApiUser { Guid = Guid.NewGuid(), Name = "YouYou", Birth = new DateTime(1992, 1, 26), RegistrationDate = new DateTime(2015, 7, 8), Passwd = "grwe874864987", ProfilePhotoUrl = "https://www.laggage.top/", PhoneNumber = "17084759987", Email = "YouYou@outlook.com" }, new ApiUser { Guid = Guid.NewGuid(), Name = "小白", Birth = new DateTime(1997, 9, 30), RegistrationDate = new DateTime(2018, 11, 28), Passwd = "gewa749864", ProfilePhotoUrl = "https://www.laggage.top/", PhoneNumber = "17084759987", Email = "BaiBai@outlook.com" }); await context.SaveChangesAsync(); } } catch(Exception ex) { ILogger logger = loggerFactory.CreateLogger<UserContextSeed>(); logger.LogError(ex, "Error occurred while seeding database"); } } } }