一, 前言
1, 本教程主要内容
ASP.NET Core MVC 集成 EF Core 介绍 & 操作步骤
ASP.NET Core MVC 使用 EF Core + Linq to Entity 访问 MySQL 数据库
ASP.NET Core MVC 使用 EF Core + 原生 SQL 访问 MySQL 数据库
EF Core + MySQL 数据库插入数据后获取自增列的值
Entity Framework Core https://docs.microsoft.com/zh-cn/ef/core 简称为 EF Core
2, 本教程环境信息
软件 / 环境 | 说明 |
---|---|
操作系统 | Windows 10 |
SDK | 2.1.401 |
ASP.NET Core | 2.1.3 |
MySQL | 8.0.x |
IDE | Visual Studio Code 1.30 |
浏览器 | Chrome 70 |
VS Code 插件 | 版本 | 说明 |
---|---|---|
C# | 1.17.1 | 提供 C# 智能感知, .NET Core 调试、编译等 |
vscdoe-solution-explorer | 0.3.1 | 提供解决方案视图 |
本篇代码以下代码进行调整:
3, 准备工作
安装 MySQL 数据库: https://dev.mysql.com/downloads/mysql/
Windows 环境
下载安装包后双击安装, 一直下一步即可.
MacOS 环境
参考:
CentOS 环境
参考: https://ken.io/note/centos-mysql8-setup
4, 前置知识
控制反转 (IoC) 原则与依赖注入(DI)
ASP.NET Core 默认集成了 DI. 所有官方模块的引入都要使用 DI 的方式引入.
https://baike.baidu.com/item/IOC
Linq 使用教程
二, EF Core + MySQL 前置准备
EF Core 全称: Entity Framework Core, 为微软为 .NET Core 平台开发的 https://baike.baidu.com/item/ORM/3583252 框架. 对应是 .NET Framework 平台的 Entity Framework(EF), 无论是 EF 还是 EF Core 都可以说是 .NET 平台开发效率最高的 ORM 框架.
1, 引入 EF Core + MySQL Provider
EF Core 已经集成在 ASP.NET Core 中, 但默认并不支持 MySQL, 如果需要连接 MySQL, 需要添加 MySQL 相关的 Provider, 这里我选择的是: Pomelo.EntityFrameworkCore.MySQL
任意命令行操作即可, 我用的是 VS Code 自带的命令行
- // 进入项目根目录: Ken.Tutorial.Web
- cd Ken.Tutorial.Web
- // 添加 Package
- dotnet add package Pomelo.EntityFrameworkCore.MySQL
这里我添加的 MySQL.Data.EntityFrameworkCore 版本是 8.0.13, 如果你想跟我使用一样的版本, 可以使用以下命令:
dotnet add package Pomelo.EntityFrameworkCore.MySQL --version 2.1.4
2, 创建 MySQL 库表
创建数据库
CREATE DATABASE ken_tutorial;
创建表
- USE ken_tutorial;
- DROP TABLE IF EXISTS `user`;
- CREATE TABLE `user` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `name` varchar(255) DEFAULT NULL,
- `age` int(11) DEFAULT NULL,
- `hobby` varchar(500) DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3, 配置链接字符串
在项目根目录 Ken.Tutorial.Web 中创建配置文件 appsettings.JSON, 并写入以下配置
- {
- "ConnectionStrings": {
- "testdb": "server=localhost;database=Ken.Tutorial;uid=root;pwd=root;"
- }
- }
4, 实体 & DbContext 准备
创建 user 表对应实体
在项目根目录 Ken.Tutorial.Web 中创建目录 Models, 并在其中创建类: UserEntity.cs
- using System;
- using System.ComponentModel.DataAnnotations;
- using System.ComponentModel.DataAnnotations.Schema;
- namespace Ken.Tutorial.Web.Models
- {
- [Table("user")]
- [Serializable]
- public class UserEntity
- {
- [Key]// 主键
- [DatabaseGenerated(DatabaseGeneratedOption.Identity)]// 自增列
- [Column("id")]
- public int Id { get; set; }
- [Column("name")]
- public string Name { get; set; }
- [Column("age")]
- public int Age { get; set; }
- [Column("hobby")]
- public string Hobby { get; set; }
- }
- }
创建 DBContext
在项目根目录 Ken.Tutorial.Web 中创建目录 Repositories, 并在其中创建类: TutorialDbContext.cs
- using System;
- using Microsoft.EntityFrameworkCore;
- using Microsoft.Extensions.Configuration;
- namespace Ken.Tutorial.Web.Repositories
- {
- public class TutorialDbContext : DbContext
- {
- private IConfiguration Configuration { get; }
- public TutorialDbContext(IConfiguration configuration)
- {
- this.Configuration = configuration;
- }
- protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
- {
- optionsBuilder.UseMySql(Configuration.GetConnectionString("testdb"));
- }
- ppublic DbSet<UserEntity> Users { get; set; }
- }
- }
TutorialDbContext 继承了 DbContext, 然后再 Context 初始化时配置 MySQL 链接.
由于 ASP.NET Core 默认使用了 DI 组件, 所以我们取配置文件, 就需要在构造函数中获取 IConfiguration 注入的实例.
在 Startup.cs 配置注入, 以便数据访问类可以访问 DI 方式获取 TutorialDbContext
- public void ConfigureServices(IServiceCollection services)
- {
- // 引入 MVC 模块
- services.AddMvc();
- // 配置 DbContext 注入
- services.AddTransient<TutorialDbContext>();
- }
三, EF Core + Linq to entity 访问数据库
1, 创建 Linq To Entity 数据访问类
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Ken.Tutorial.Web.Models;
- namespace Ken.Tutorial.Web.Repositories
- {
- public class TutorialRepository
- {
- private TutorialDbContext DbContext { get; }
- public TutorialRepository(TutorialDbContext dbContext)
- {
- // 在构造函数中注入 DbContext
- this.DbContext = dbContext;
- }
- // 添加
- public int Add(UserEntity user)
- {
- using (DbContext)
- {
- // 由于我们在 UserEntity.Id 配置了自增列的 Attribute,EF 执行完成后会自动把自增列的值赋值给 user.Id
- DbContext.Users.Add(user);
- return DbContext.SaveChanges();
- }
- }
- // 删除
- public int Delete(int id)
- {
- using (DbContext)
- {
- var userFromContext = DbContext.Users.FirstOrDefault(u => u.Id == id);
- DbContext.Users.Remove(userFromContext);
- return DbContext.SaveChanges();
- }
- }
- // 更新
- public int Update(UserEntity user)
- {
- using (DbContext)
- {
- var userFromContext = DbContext.Users.FirstOrDefault(u => u.Id == user.Id);
- userFromContext.Name = user.Name;
- userFromContext.Age = user.Age;
- userFromContext.Hobby = user.Hobby;
- return DbContext.SaveChanges();
- }
- }
- // 查询
- public UserEntity QueryById(int id)
- {
- using (DbContext)
- {
- return DbContext.Users.FirstOrDefault(u => u.Id == id);
- }
- }
- // 查询集合
- public List<UserEntity> QueryByAge(int age)
- {
- using (DbContext)
- {
- return DbContext.Users.Where(u => u.Age == age).ToList();
- }
- }
- // 查看指定列
- public List<string> QueryNameByAge(int age)
- {
- using (DbContext)
- {
- return DbContext.Users.Where(u => u.Age == age).Select(u => u.Name).ToList();
- }
- }
- // 分页查询
- public List<UserEntity> QueryUserPaging(int pageSize, int page)
- {
- using (DbContext)
- {
- return DbContext.Users.Skip(pageSize * (page - 1)).Take(pageSize).ToList();
- }
- }
- // 事务: 将年龄 < 0 的用户修改年龄为 0
- public int FixAge()
- {
- using (DbContext)
- {
- using (var transaction = DbContext.Database.BeginTransaction())
- {
- try
- {
- var userListFromContext = DbContext.Users.Where(u => u.Age <0);
- foreach (UserEntity u in userListFromContext)
- {
- u.Age = 0;
- }
- var count = DbContext.SaveChanges();
- transaction.Commit();
- return count;
- }
- catch
- {
- transaction.Rollback();
- return 0;
- }
- }
- }
- }
- }
- }
2, 创建测试 API
在 Controllers 文件夹下创建 EfCoreController.cs 作为访问入口
- using System;
- using Ken.Tutorial.Web.Models;
- using Ken.Tutorial.Web.Repositories;
- using Microsoft.AspNetCore.Mvc;
- namespace Ken.Tutorial.Web.Controllers
- {
- public class EfCoreController : Controller
- {
- public TutorialRepository Repository { get; }
- public EfCoreController(TutorialRepository repository)
- {
- this.Repository = repository;
- }
- public IActionResult Add(UserEntity user)
- {
- var message = Repository.Add(user)> 0 ? "success" : "failed";
- return JSON(new { Message = message, User = user });
- }
- public IActionResult Delete(int id)
- {
- var message = Repository.Delete(id)> 0 ? "success" : "failed";
- return JSON(new { Message = message });
- }
- public IActionResult Update(UserEntity user)
- {
- var message = Repository.Update(user)> 0 ? "success" : "failed";
- return JSON(new { Message = message, User = user });
- }
- public IActionResult QueryById(int id)
- {
- var user = Repository.QueryById(id);
- return JSON(new { User = user });
- }
- public IActionResult QueryByAge(int age)
- {
- var users = Repository.QueryByAge(age);
- return JSON(new { Users = users });
- }
- public IActionResult QueryNameByAge(int age)
- {
- var users = Repository.QueryNameByAge(age);
- return JSON(new { Users = users });
- }
- public IActionResult QueryUserPaging(int pageSize, int page)
- {
- var users = Repository.QueryUserPaging(pageSize, page);
- return JSON(new { Users = users });
- }
- public IActionResult FixAge()
- {
- var count = Repository.FixAge();
- return JSON(new { FixCount = count });
- }
- }
- }
3, 启动测试
在 Startup.cs 中配置 Repository 注入
- public void ConfigureServices(IServiceCollection services)
- {
- // 其他代码省略
- // 配置 Repository 注入
- services.AddTransient<TutorialRepository>();
- }
启动项目并测试
API | 示例 |
---|---|
添加用户 | /efcore/add?name=ken&age=18&hobby=coding |
删除用户 | /efcore/delete?id=0 |
更新用户 | /efcore/update?id=1&name=ken&age=666&hobby=codingOrGaming |
查询单个用户 | /efcore/querybyid?id=0 |
查询多个用户 | /efcore/querybyage?age=18 |
查询多个用户名 | /efcore/querynamebyage?age=18 |
分页查询用户 | /efcore/queryuserpaging?pagesize=3&page=1 |
修复异常年龄 | /efcore/fixage |
四, EF Core + 原生 SQL 访问数据库
1, 创建 EF Core + 原生 SQL 数据访问类
- using System;
- using System.Collections.Generic;
- using System.Data;
- using System.Data.SqlClient;
- using System.Linq;
- using Ken.Tutorial.Web.Models;
- using Microsoft.EntityFrameworkCore;
- using MySQL.Data.MySqlClient;
- namespace Ken.Tutorial.Web.Repositories
- {
- public class TutorialWithSqlRepository
- {
- private TutorialDbContext DbContext { get; }
- public TutorialWithSqlRepository(TutorialDbContext dbContext)
- {
- // 在构造函数中注入 DbContext
- this.DbContext = dbContext;
- }
- // 添加
- public int Add(UserEntity user)
- {
- using (var connection = DbContext.Database.GetDbConnection())
- {
- connection.Open();
- var command = connection.CreateCommand() as MySqlCommand;
- command.CommandText = "INSERT INTO user (name,age,hobby) VALUES(@name,@age,@hobby)";
- command.Parameters.Add(new MySqlParameter()
- {
- ParameterName = "@name",
- DbType = DbType.String,
- Value = user.Name
- });
- command.Parameters.Add(new MySqlParameter()
- {
- ParameterName = "@age",
- DbType = DbType.Int32,
- Value = user.Age
- });
- command.Parameters.Add(new MySqlParameter()
- {
- ParameterName = "@hobby",
- DbType = DbType.String,
- Value = user.Hobby
- });
- var count = command.ExecuteNonQuery();
- // 获取插入时产生的自增列 Id 并赋值给 user.Id 使用
- user.Id = (int)command.LastInsertedId;
- return count;
- }
- }
- // 删除
- public int Delete(int id)
- {
- using (DbContext)
- {
- return DbContext.Database.ExecuteSqlCommand(
- "DELETE FROM user WHERE id={0}", id);
- }
- }
- // 更新
- public int Update(UserEntity user)
- {
- using (DbContext)
- {
- return DbContext.Database.ExecuteSqlCommand(
- "UPDATE user SET name={0}, age={1}, hobby={2} WHERE id={3}",
- user.Name, user.Age, user.Hobby, user.Id);
- }
- }
- // 查询
- public UserEntity QueryById(int id)
- {
- using (DbContext)
- {
- return DbContext.Users.FromSql("SELECT id,name,age,hobby FROM user WHERE id={0}", id).FirstOrDefault();
- }
- }
- // 查询集合
- public List<UserEntity> QueryByAge(int age)
- {
- using (DbContext)
- {
- return DbContext.Users.FromSql("SELECT id,name,age,hobby FROM user WHERE age={0}", age).ToList();
- }
- }
- // 查看指定列
- public List<string> QueryNameByAge(int age)
- {
- using (DbContext)
- {
- return DbContext.Users.FromSql("SELECT id,name FROM user WHERE age={0}", age).Select(u => u.Name).ToList();
- }
- }
- // 分页查询
- public List<UserEntity> QueryUserPaging(int pageSize, int page)
- {
- using (DbContext)
- {
- return DbContext.Users.FromSql("SELECT id,name,age,hobby FROM user LIMIT {0},{1}", pageSize * (page - 1), pageSize).ToList();
- }
- }
- // 事务: 将年龄 < 0 的用户修改年龄为 0
- public int FixAge()
- {
- using (DbContext)
- {
- using (var connection = DbContext.Database.GetDbConnection())
- {
- // 打开连接
- connection.Open();
- // 开启事务
- using (var transaction = connection.BeginTransaction())
- {
- try
- {
- // 获取命令对象
- var command = connection.CreateCommand();
- command.Transaction = transaction;
- command.CommandText = "UPDATE user SET age=@age WHERE age<@age";
- command.Parameters.Add(new MySqlParameter()
- {
- ParameterName = "@age",
- DbType = DbType.Int32,
- Value = 0
- });
- var count = command.ExecuteNonQuery();
- transaction.Commit();
- return count;
- }
- catch (Exception ex)
- {
- connection.Close();
- transaction.Rollback();
- return 0;
- }
- }
- }
- }
- }
- }
- }
2, 创建测试 API
在 Controllers 文件夹下创建 EfCoreWithSqlController.cs 作为访问入口
- using System;
- using Ken.Tutorial.Web.Models;
- using Ken.Tutorial.Web.Repositories;
- using Microsoft.AspNetCore.Mvc;
- namespace Ken.Tutorial.Web.Controllers
- {
- public class EfCoreWithSqlController : Controller
- {
- public TutorialWithSqlRepository Repository { get; }
- public EfCoreWithSqlController(TutorialWithSqlRepository repository)
- {
- this.Repository = repository;
- }
- public IActionResult Add(UserEntity user)
- {
- var message = Repository.Add(user)> 0 ? "success" : "failed";
- return JSON(new { Message = message, User = user });
- }
- public IActionResult Delete(int id)
- {
- var message = Repository.Delete(id)> 0 ? "success" : "failed";
- return JSON(new { Message = message });
- }
- public IActionResult Update(UserEntity user)
- {
- var message = Repository.Update(user)> 0 ? "success" : "failed";
- return JSON(new { Message = message, User = user });
- }
- public IActionResult QueryById(int id)
- {
- var user = Repository.QueryById(id);
- return JSON(new { User = user });
- }
- public IActionResult QueryByAge(int age)
- {
- var users = Repository.QueryByAge(age);
- return JSON(new { Users = users });
- }
- public IActionResult QueryNameByAge(int age)
- {
- var users = Repository.QueryNameByAge(age);
- return JSON(new { Users = users });
- }
- public IActionResult QueryUserPaging(int pageSize, int page)
- {
- var users = Repository.QueryUserPaging(pageSize, page);
- return JSON(new { Users = users });
- }
- public IActionResult FixAge()
- {
- var count = Repository.FixAge();
- return JSON(new { FixCount = count });
- }
- }
- }
3, 启动测试
在 Startup.cs 中配置 Repository 注入
- public void ConfigureServices(IServiceCollection services)
- {
- // 其他代码省略
- // 配置 Repository 注入
- services.AddTransient<TutorialWithSqlRepository>();
- }
启动项目并测试
API | 示例 |
---|---|
添加用户 | /efcorewithsql/add?name=ken&age=18&hobby=coding |
删除用户 | /efcorewithsql/delete?id=0 |
更新用户 | /efcorewithsql/update?id=1&name=ken&age=666&hobby=codingOrGaming |
查询单个用户 | /efcorewithsql/querybyid?id=0 |
查询多个用户 | /efcorewithsql/querybyage?age=18 |
查询多个用户名 | /efcorewithsql/querynamebyage?age=18 |
分页查询用户 | /efcorewithsql/queryuserpaging?pagesize=3&page=1 |
修复异常年龄 | /efcorewithsql/fixage |
五, 备注
1, 附录
本文代码示例
本文参考
- https://docs.microsoft.com/zh-cn/ef/core
- https://www.learnentityframeworkcore.com/
本文首发于我的独立博客:
来源: https://www.cnblogs.com/ken-io/p/aspnet-core-tutorial-entity-framework-core-mysql.html