一、前言 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數 ...
一、前言
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 簡稱為 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 | 提供解決方案視圖 |
本篇代碼以下代碼進行調整:https://github.com/ken-io/asp.net-core-tutorial/tree/master/chapter-02
3、準備工作
安裝MySQL資料庫:https://dev.mysql.com/downloads/mysql/
- Windows環境
下載安裝包後雙擊安裝,一直下一步即可。
- MacOS環境
參考:https://ken.io/note/macos-mysql8-install-config-tutorial
- CentOS環境
參考:https://ken.io/note/centos-mysql8-setup
4、前置知識
- 控制反轉(IOC)原則與依賴註入(DI)
ASP.NET Core 預設集成了DI。所有官方模塊的引入都要使用DI的方式引入。
https://baike.baidu.com/item/IOC
- Linq使用教程
https://docs.microsoft.com/zh-cn/dotnet/csharp/tutorials/working-with-linq
二、EF Core + MySQL 前置準備
EF Core 全稱:Entity Framework Core,為微軟為 .NET Core平臺開發的ORM框架。對應是 .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://github.com/ken-io/asp.net-core-tutorial/tree/master/chapter-08
- 本文參考
https://docs.microsoft.com/zh-cn/ef/core
https://www.learnentityframeworkcore.com
https://mysql-net.github.io/MySqlConnector/tutorials/net-core-mvc/
本文首發於我的獨立博客:https://ken.io/note/asp.net-core-tutorial-entity-framework-core-mysql