1、配置数据库
首先连接数据库


然后连接已有数据库,或者是创建新的数据库

随后在选择的数据库中选择或创建新的表,并且添加初始数据

由于是利用软件自动生成的数据,数据以仅作示例,没有特定含义。

2、配置 MySQL 所需包
在使用数据库时,由于可能不包含必要的数据库插件,所以需要安装以下NuGet包,并且需要注意版本一致性:
- Microsoft.EntityFrameworkCore
- Microsoft.EntityFrameworkCore.Design
- Microsoft.EntityFrameworkCore.Tools
- Pomelo.EntityFrameworkCore.MySql

3、配置 MySQL 上下文
TodoItemDbContext 类,它是一个 Entity Framework Core (EF Core) 的数据库上下文类,主要用于管理与数据库的交互。TodoItemDbContext 继承自 DbContext,是 EF Core 的核心组件,用于:定义数据库表与实体类的映射关系。提供对数据库的访问接口(如查询、插入、更新、删除操作)。管理数据库连接和事务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using WebApp.Pojo.Entity;
namespace WebApp.DB { public class TodoItemDbContext : DbContext { public DbSet<TodoItem> TodoItems { get; set; }
public TodoItemDbContext(DbContextOptions<TodoItemDbContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<TodoItem>().ToTable("todo_item"); } } }
|
注释说明
- 类级别注释:
TodoItemDbContext 是数据库上下文类,继承自 DbContext,用于管理与数据库的交互。
- 它是
Entity Framework Core 的核心组件,负责查询、保存和管理实体。
- 属性注释:
DbSet<TodoItem> 是 EF Core 中的一个集合,表示数据库中的一张表。
- 在这里,
TodoItems 映射到数据库中的 todo_item 表。
- 构造函数注释:
- 构造函数通过依赖注入接收
DbContextOptions,用于配置数据库连接(如连接字符串、数据库提供程序等)。
- 方法注释:
OnModelCreating 方法用于配置实体与数据库表的映射关系。
- 使用
ToTable("todo_item")显式指定 TodoItem 实体映射到数据库表 todo_item。
代码功能总结
- 数据库上下文:
TodoItemDbContext 是应用程序与数据库之间的桥梁。
- 它管理
TodoItem实体的CRUD操作。
- 表名映射:
- 使用
ToTable("todo_item")将 TodoItem实体映射到数据库表 todo_item,确保表名一致。
- 依赖注入:
- 通过构造函数注入
DbContextOptions,支持灵活的数据库配置。
4、配置 MySQL 连接字符串
在 appsettings.json 文件中添加 MySQL 的连接字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| { "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "ConnectionStrings": { "DefaultConnection": "server=localhost;port=3306;database=aspnetcore;uid=root;pwd=root;" }, "AllowedHosts": "*" }
|
5、在 Program.cs 中配置 MySQL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
using Microsoft.EntityFrameworkCore; using WebApp.Config; using WebApp.DB;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoItemDbContext>(options => options.UseMySql( builder.Configuration.GetConnectionString("DefaultConnection"), new MySqlServerVersion(new Version(8, 0, 34)) ) );
builder.Services.AddControllers();
builder.Services.RegisterAllServices();
var app = builder.Build();
app.MapControllers();
app.Run();
|
详细解析
- AddDbContext
- 作用:
- 将 TodoItemDbContext 注册到 ASP.NET Core 的依赖注入容器中。
- 允许应用程序的其他部分(如控制器或服务)通过构造函数注入的方式使用 TodoItemDbContext。
- 参数:
- TodoItemDbContext:数据库上下文类,继承自 DbContext,用于管理与数据库的交互。
- options:配置数据库上下文的选项(如数据库提供程序、连接字符串等)。
- UseMySql
作用:
- 配置 EF Core 使用 MySQL 作为数据库提供程序。
- 告诉 EF Core 如何连接到 MySQL 数据库。
参数:
连接字符串:
- 通过 builder.Configuration.GetConnectionString(“DefaultConnection”) 从 appsettings.json 中读取连接字符串。
- 连接字符串包含数据库服务器地址、端口、数据库名称、用户名和密码。
示例连接字符串:
1
| "DefaultConnection": "server=localhost;port=3306;database=aspnetcore;uid=root;pwd=root;"
|
- MySQL 版本:
- 使用 new MySqlServerVersion(new Version(8, 0, 34)) 指定 MySQL 数据库的版本。
- 这是 Pomelo.EntityFrameworkCore.MySql 提供程序的要求,用于优化 SQL 生成和功能支持。
- builder.Configuration.GetConnectionString
- 作用:
- 从配置文件(如 appsettings.json)中读取连接字符串。
- 确保数据库连接信息可以集中管理,便于在不同环境(如开发、测试、生产)中使用不同的配置。
依赖注入的作用
- 注册到容器:
- AddDbContext 将 TodoItemDbContext 注册为服务,允许在应用程序的其他部分通过构造函数注入使用它。
- 生命周期:
- 默认情况下,AddDbContext 使用 Scoped 生命周期:
- 每个 HTTP 请求创建一个新的 TodoItemDbContext 实例。
- 同一请求中的所有服务共享同一个实例。
代码在程序中的作用
- 数据库连接管理:
- 通过 AddDbContext 和 UseMySql 配置数据库连接,确保应用程序可以与 MySQL 数据库交互。
- 依赖注入支持:
- 将 TodoItemDbContext 注册到依赖注入容器中,允许控制器或服务通过构造函数注入使用它。
- 灵活的配置管理:
- 使用 appsettings.json 管理连接字符串,便于在不同环境中切换数据库配置。
- MySQL 优化:
- 通过指定 MySQL 版本,EF Core 可以生成针对特定版本优化的 SQL 查询。
6、创建实体模型
依据创建的数据库表重新构建pojo中的内容。
Pojo\DTO\TodoItemDTO.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| namespace WebApp.Pojo.DTO { public class TodoItemDTO { public int Id { get; set; }
public string? Name { get; set; }
public int IsComplete { get; set; } } }
|
Pojo\Entity\TodoItem.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| namespace WebApp.Pojo.Entity { public class TodoItem { private int TodoId { get; set; }
public int Id { get; set; }
public string? Name { get; set; }
public int IsComplete { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public DateTime? DeletedAt { get; set; }
public TodoItem() { }
public TodoItem(int todoId, int id, string? name, int isComplete, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt = null) { TodoId = todoId; Id = id; Name = name; IsComplete = isComplete; CreatedAt = createdAt; UpdatedAt = updatedAt; DeletedAt = deletedAt; } } }
|
在 Entity Framework Core (EF Core) 或其他类似框架中,默认构造函数(无参数构造函数)是必需的或推荐的,主要是因为这些框架在实例化实体对象时需要遵循特定的规则。以下是详细的原因和解释:
- EF Core 如何实例化实体对象
EF Core 使用反射(Reflection)来实例化实体对象。当从数据库中查询数据时,EF Core 会:
- 创建实体对象:通过调用实体类的默认构造函数(无参数构造函数)。
- 设置属性值:将数据库中的列值绑定到实体对象的属性。
如果实体类没有默认构造函数,EF Core 将无法实例化该类的对象,从而导致运行时错误。
默认构造函数的作用
- 支持反射实例化
- EF Core 使用反射来创建对象,而反射需要一个无参数的构造函数来实例化类。如果没有默认构造函数,EF Core 无法通过反射创建对象。
- 支持延迟加载(Lazy Loading)
- 在启用延迟加载时,EF Core 可能会动态代理实体类(创建派生类)。默认构造函数是动态代理生成的关键要求。
- 支持属性绑定
- EF Core 在实例化对象后,会逐一设置属性值。如果没有默认构造函数,EF Core 无法创建对象,也就无法设置属性值。
- 为什么完整构造函数不足以替代默认构造函数?
虽然实体类可以定义带参数的完整构造函数,但 EF Core 无法自动将数据库列值绑定到构造函数的参数。原因如下:
- 参数名与列名可能不匹配:
- EF Core 依赖属性名与数据库列名匹配,而构造函数的参数名可能与列名不同。
- 绑定复杂性:
- EF Core 无法解析复杂的构造函数逻辑(如参数的默认值或计算逻辑)。
- 灵活性不足:
- 如果只有带参数的构造函数,EF Core 无法支持动态代理或延迟加载。
Pojo\VO\TodoItemVO.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| namespace WebApp.Pojo.VO { public class TodoItemVO { public int Id { get; set; }
public string? Name { get; set; }
public int IsComplete { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public DateTime? DeletedAt { get; set; } } }
|
7、使用数据库
在Mapper中使用数据库
Mapper\ITodoItemMapper.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| using WebApp.Pojo.Entity;
namespace WebApp.Mapper { public interface ITodoItemMapper { public List<TodoItem> GetAllTodoItems();
public TodoItem GetTodoItemById(int id);
public void AddTodoItem(TodoItem todoItem);
public void UpdateTodoItem(int id, TodoItem todoItem);
public void DeleteTodoItem(int id); } }
|
Mapper\Impl\TodoItemMapperImpl.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| using WebApp.DB; using WebApp.Pojo.Entity;
namespace WebApp.Mapper.Impl { public class TodoItemMapperImpl : ITodoItemMapper { private readonly TodoItemDbContext _context;
public TodoItemMapperImpl(TodoItemDbContext todoItemDbContext) { _context = todoItemDbContext; }
public List<TodoItem> GetAllTodoItems() { return _context.TodoItems.ToList(); }
public TodoItem GetTodoItemById(int id) { return _context.TodoItems.Find(id); }
public void AddTodoItem(TodoItem todoItem) { _context.TodoItems.Add(todoItem); _context.SaveChanges(); }
public void UpdateTodoItem(int id, TodoItem todoItem) { _context.TodoItems.Update(todoItem); _context.SaveChanges(); }
public void DeleteTodoItem(int id) { var item = _context.TodoItems.Find(id); if (item != null) { _context.TodoItems.Remove(item); _context.SaveChanges(); } } } }
|
8、构建完整代码
Services\ITodoItemService.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| using WebApp.Pojo.DTO; using WebApp.Pojo.Entity; using WebApp.Pojo.VO;
namespace WebApp.Services { public interface ITodoItemService { public List<TodoItemVO> GetAllTodoItems();
public TodoItemVO GetTodoItemById(int id);
public TodoItemVO AddTodoItem(TodoItemDTO todoItemDTO);
public TodoItemVO UpdateTodoItem(int id, TodoItemDTO todoItemDTO);
public TodoItemVO DeleteTodoItem(int id); } }
|
Services\Impl\TodoItemServiceImpl.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
| using WebApp.Mapper; using WebApp.Pojo.DTO; using WebApp.Pojo.Entity; using WebApp.Pojo.VO;
namespace WebApp.Services.Impl { public class TodoItemServiceImpl : ITodoItemService { private readonly ITodoItemMapper _todoItemMapper;
public TodoItemServiceImpl(ITodoItemMapper todoItemMapper) { _todoItemMapper = todoItemMapper; }
public List<TodoItemVO> GetAllTodoItems() { List<TodoItem> todoItems = _todoItemMapper.GetAllTodoItems();
return todoItems.Select(item => new TodoItemVO { Id = item.Id, Name = item.Name, IsComplete = item.IsComplete, CreatedAt = item.CreatedAt, UpdatedAt = item.UpdatedAt, DeletedAt = item.DeletedAt }).ToList(); }
public TodoItemVO GetTodoItemById(int id) { TodoItem todoItem = _todoItemMapper.GetTodoItemById(id);
if (todoItem == null) { throw new Exception("Todo item not found"); }
return new TodoItemVO { Id = todoItem.Id, Name = todoItem.Name, IsComplete = todoItem.IsComplete, CreatedAt = todoItem.CreatedAt, UpdatedAt = todoItem.UpdatedAt, DeletedAt = todoItem.DeletedAt }; }
public TodoItemVO AddTodoItem(TodoItemDTO todoItemDTO) { TodoItem todoItem = new TodoItem( todoId: Random.Shared.Next(), id: todoItemDTO.Id, name: todoItemDTO.Name, isComplete: todoItemDTO.IsComplete, createdAt: DateTime.Now, updatedAt: DateTime.Now);
_todoItemMapper.AddTodoItem(todoItem);
TodoItem todoItemCreate = _todoItemMapper.GetTodoItemById(todoItemDTO.Id); if (todoItem == null) { throw new Exception("Todo item not found"); }
return new TodoItemVO { Id = todoItem.Id, Name = todoItem.Name, IsComplete = todoItem.IsComplete, CreatedAt = todoItem.CreatedAt, UpdatedAt = todoItem.UpdatedAt, DeletedAt = todoItem.DeletedAt }; }
public TodoItemVO UpdateTodoItem(int id, TodoItemDTO todoItemDTO) { TodoItem todoItem = _todoItemMapper.GetTodoItemById(id);
if (todoItem == null) { throw new Exception("Todo item not found"); }
todoItem.Id = todoItemDTO.Id; todoItem.Name = todoItemDTO.Name; todoItem.IsComplete = todoItemDTO.IsComplete; todoItem.UpdatedAt = DateTime.Now;
_todoItemMapper.UpdateTodoItem(id, todoItem);
TodoItem todoItemUpdate = _todoItemMapper.GetTodoItemById(todoItemDTO.Id); if (todoItem == null) { throw new Exception("Todo item not found"); }
return new TodoItemVO { Id = todoItem.Id, Name = todoItem.Name, IsComplete = todoItem.IsComplete, CreatedAt = todoItem.CreatedAt, UpdatedAt = todoItem.UpdatedAt, DeletedAt = todoItem.DeletedAt }; }
public TodoItemVO DeleteTodoItem(int id) { TodoItem todoItem = _todoItemMapper.GetTodoItemById(id);
if (todoItem == null) { throw new Exception("Todo item not found"); }
TodoItemVO result = new TodoItemVO { Id = todoItem.Id, Name = todoItem.Name, IsComplete = todoItem.IsComplete, CreatedAt = todoItem.CreatedAt, UpdatedAt = todoItem.UpdatedAt, DeletedAt = todoItem.DeletedAt };
_todoItemMapper.DeleteTodoItem(id);
return result; } } }
|
Controllers\TodoItemController.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
| using Microsoft.AspNetCore.Mvc; using WebApp.Pojo.DTO; using WebApp.Pojo.VO; using WebApp.Services;
namespace WebApp.Controllers { [ApiController] [Route("api/[controller]")] public class TodoItemController : ControllerBase { private readonly ITodoItemService _todoItemService;
public TodoItemController(ITodoItemService todoItemService) { _todoItemService = todoItemService; }
[HttpGet] public ActionResult<List<TodoItemVO>> GetAllTodoItems() { List<TodoItemVO> todoItemVOs = _todoItemService.GetAllTodoItems();
return Ok(todoItemVOs); }
[HttpGet("{id}")] public ActionResult<TodoItemVO> GetTodoItemById(int id) { TodoItemVO todoItemVO = _todoItemService.GetTodoItemById(id);
return Ok(todoItemVO); }
[HttpPost] public ActionResult<TodoItemVO> AddTodoItem([FromBody] TodoItemDTO todoItem) { TodoItemVO todoItemVO = _todoItemService.AddTodoItem(todoItem);
return Ok(todoItemVO); }
[HttpPut("{id}")] public ActionResult<TodoItemVO> UpdateTodoItem(int id, [FromBody] TodoItemDTO todoItem) { TodoItemVO todoItemVO = _todoItemService.UpdateTodoItem(id, todoItem);
return Ok(todoItemVO); }
[HttpDelete("{id}")] public ActionResult<TodoItemVO> DeleteTodoItem(int id) { TodoItemVO todoItemVO = _todoItemService.DeleteTodoItem(id);
return Ok(todoItemVO); } } }
|
9、结果可视化
1、查询全部


2、单独查询全部

3、添加新内容


4、改数据


5、删除数据

