From ce994ee2e0cf5109cb3c6432fe6cf36fe0806d03 Mon Sep 17 00:00:00 2001 From: xxx Date: Sun, 9 Jun 2024 22:14:17 +0800 Subject: [PATCH] bj --- ...1\347\233\256\345\256\236\347\216\2601.md" | 165 ++++++++++++++++++ ...1\347\233\256\345\256\236\347\216\2602.md" | 159 +++++++++++++++++ ...0240606-EFCore\344\273\213\347\273\215.md" | 65 +++++++ ...0240607-EFcore\344\275\277\347\224\250.md" | 96 ++++++++++ 4 files changed, 485 insertions(+) create mode 100644 "\347\274\252\346\242\223\344\272\250/20240603-\351\241\271\347\233\256\345\256\236\347\216\2601.md" create mode 100644 "\347\274\252\346\242\223\344\272\250/20240605-\351\241\271\347\233\256\345\256\236\347\216\2602.md" create mode 100644 "\347\274\252\346\242\223\344\272\250/20240606-EFCore\344\273\213\347\273\215.md" create mode 100644 "\347\274\252\346\242\223\344\272\250/20240607-EFcore\344\275\277\347\224\250.md" diff --git "a/\347\274\252\346\242\223\344\272\250/20240603-\351\241\271\347\233\256\345\256\236\347\216\2601.md" "b/\347\274\252\346\242\223\344\272\250/20240603-\351\241\271\347\233\256\345\256\236\347\216\2601.md" new file mode 100644 index 0000000..a4de595 --- /dev/null +++ "b/\347\274\252\346\242\223\344\272\250/20240603-\351\241\271\347\233\256\345\256\236\347\216\2601.md" @@ -0,0 +1,165 @@ +## Dto的好处 +1. 数据封装与传输:DTO用于在不同层之间传递数据,特别是在控制器和服务层之间。它能够将请求中的数据进行封装,从而便于传输。 +2. 解耦:通过使用DTO,可以避免直接暴露数据库模型(这里指Domain中的文件),从而降低各层之间的耦合度。 +3. 数据验证与格式化:DTO可以添加数据注释和验证属性,确保传入的数据符合预期格式和约束。这样可以在数据到达业务逻辑层之前进行初步验证。 +4. 安全性:可以避免将敏感的数据库字段直接暴露给客户端。 +5. 数据转换:以用于将复杂的数据结构转换为适合传输的简单结构,或者将客户端传入的数据转换为适合业务逻辑处理的结构。 + +## 使用Dto的写法(记得引入Dto) +### Interfaces接口 +```cs +public interface IAuthorRepository +{ + // 获取全部作者 + ICollection GetAllAuthors(); + // 获取指定id作者 + AuthorDto? GetAuthorById(Guid id); + // 添加作者 + AuthorDto AddAuthor(CreateAuthorDto createAuthorDto); + // 修改作者 + AuthorDto? UpdateAuthor(Guid id, UpdateAuthorDto updateAuthorDto); + // 删除作者 + string DelAuthor(Guid id); +} +``` +### Service实现接口——增删改查的操作都写在这里 +```cs +//-------------------获取全部作者------------------------------ + public ICollection GetAllAuthors() + { + // 用于存储转换为Dto类型后的作者信息 + var resList = new List(); + var list = BookStoreDb.Instance.Authors.ToList(); + list.ForEach(item => { + // 将数据转换为Dto对象,并添加到resList中 + /* 实例化一个对象有2种方式: + 1.直接调用构造函数,形如:new AuthorDto(......) + 2.直接填充其属性值,形如:new AuthorDto{......},像下面一样 + */ + resList.Add(new AuthorDto{ + Id = item.Id, + AuthorName = item.AuthorName, + Gender = item.Gender + }); + }); + return resList; + } +//-------------------获取指定id作者------------------------------ + public AuthorDto? GetAuthorById(Guid id) + { + var tmp = BookStoreDb.Instance.Authors.SingleOrDefault(item => item.Id == id); + /* + 如果匹配的结果tmp不为null,则则创建一个新的 AuthorDto 对象(tmpResult),并将 tmp 中的属性值赋给它 + 如果没有找到匹配的结果,则将tmpResult 设置为 null + */ + var tmpResult = tmp != null? new AuthorDto{ + Id = tmp.Id, + AuthorName = tmp.AuthorName, + Gender = tmp.Gender + }:null; + return tmpResult; + } +//-------------------添加作者------------------------------ + public AuthorDto AddAuthor(CreateAuthorDto createAuthorDto) + { + // 将传入的dto转换为保存到内存数据库需要的实体类型Authors + var author = new Authors{ + Id = Guid.NewGuid(), + AuthorName = createAuthorDto.AuthorName, + Gender = createAuthorDto.Gender, + Birthday = createAuthorDto.Birthday + }; + // 添加操作 + BookStoreDb.Instance.Authors.Add(author); + // 将内存数据库获取的数据转换为AuthorDto的实例,以Dto类型返回 + var authorDto = new AuthorDto{ + Id = author.Id, + AuthorName = author.AuthorName, + Gender = author.Gender, + }; + return authorDto; + } +//-------------------修改作者------------------------------ + public AuthorDto? UpdateAuthor(Guid id, UpdateAuthorDto updateAuthorDto) + { + // 查找指定id数据 + var item = BookStoreDb.Instance.Authors.SingleOrDefault(item => item.Id == id); + // 未找到就返回null + if(item == null){ + return null; + } + // 找到后就进行数据更新 + item.AuthorName = updateAuthorDto.AuthorName; + item.Gender = updateAuthorDto.Gender; + item.Birthday = updateAuthorDto.Birthday; + // 根据更新后的作者信息创建一个新的dto对象 + var res = new AuthorDto{ + Id = item.Id, + AuthorName = item.AuthorName, + Gender = item.Gender + }; + return res; + } +//-------------------删除作者------------------------------ + //这里尝试返回string类型,成功! + public string DelAuthor(Guid id) + { + var item = BookStoreDb.Instance.Authors.SingleOrDefault(item => item.Id == id); + if(item != null){ + var delAuthor = BookStoreDb.Instance.Authors.Remove(item); + return "删除成功"; + + }else{ + return "未找到删除对象"; + } + } +``` +### 控制器——调用函数,尽量保持纯洁性 + +```cs +// -----------------获取------------------------------------------ + [HttpGet("{id?}",Name = nameof(Get))] + public IActionResult Get(Guid id) + { + var noId = "00000000-0000-0000-0000-000000000000"; + if(id.ToString()==noId){ + var list = _authorRepsitory.GetAllAuthors(); + return Ok(list); + }else{ + var item = _authorRepsitory.GetAuthorById(id); + return Ok(item); + } + } +// -----------------添加------------------------------------------ + [HttpPost] + public IActionResult Post(CreateAuthorDto createAuthorDto) + { + /* 1.拿到CreateAuthorDto类型的实例化数据--模型绑定 + 2.将相关数据保存到数据库: + 1. 转换CreateAuthorDto类型的数据为Authors类型 + 2. 调用数据库上下文,将数据插入 + */ + var res = _authorRepsitory.AddAuthor(createAuthorDto); + if(res == null){ + return Ok("添加失败"); + } + return Ok("添加成功"); + } +// -----------------修改------------------------------------------ + [HttpPut("{id}")] + public IActionResult Put(Guid id,UpdateAuthorDto updateAuthorDto) + { + var res = _authorRepsitory.UpdateAuthor(id,updateAuthorDto); + if(res == null){ + return Ok("修改失败"); + } + return Ok("修改成功"); + } +// -----------------删除------------------------------------------ + [HttpDelete("{id}")] + public IActionResult Del(Guid id) + { + var res = _authorRepsitory.DelAuthor(id); + return Ok(res); + } +``` \ No newline at end of file diff --git "a/\347\274\252\346\242\223\344\272\250/20240605-\351\241\271\347\233\256\345\256\236\347\216\2602.md" "b/\347\274\252\346\242\223\344\272\250/20240605-\351\241\271\347\233\256\345\256\236\347\216\2602.md" new file mode 100644 index 0000000..749620a --- /dev/null +++ "b/\347\274\252\346\242\223\344\272\250/20240605-\351\241\271\347\233\256\345\256\236\347\216\2602.md" @@ -0,0 +1,159 @@ +## 一、配置接口 +```js +public interface IBookRepository +{ + // 获取指定id图书 + BookDto? GetBookById(Guid id); + // 获取全部图书 + ICollection GetAllBooks(Guid authorId); + // 添加图书 + BookDto AddBook(Guid authorId,AddBookDto addBookDto); + // 修改图书 + BookDto? UpdateBook(Guid bookId,BookDtoUpdate bookDtoUpdate); + // 删除图书 + string DelBook(Guid bookId); +} +``` +## 二、实现接口 +```js +// 添加图书 +public BookDto AddBook(Guid authorId,AddBookDto addBookDto) +{ + var book = new Books{ + Id = Guid.NewGuid(), + BooksName = addBookDto.BooksName, + Publiser = addBookDto.Publiser, + Price = addBookDto.Price, + AuthorId = authorId + }; + BookStoreDb.Instance.Books.Add(book); + var bookDto = new BookDto{ + Id = book.Id, + BooksName = book.BooksName, + Publiser = book.Publiser, + Price = book.Price, + AuthorId = book.AuthorId + }; + return bookDto; +} +// 获取全部图书 +public ICollection GetAllBooks(Guid authorId) +{ + var resList = new List(); + var list = BookStoreDb.Instance.Books.Where(b => b.AuthorId == authorId).ToList(); + list.ForEach(item => { + resList.Add(new BookDto{ + Id = item.Id, + BooksName = item.BooksName, + Publiser = item.Publiser, + Price = item.Price, + AuthorId = item.AuthorId + }); + }); + return resList; +} +// 获取指定id图书 +public BookDto? GetBookById(Guid id) +{ + var tmp = BookStoreDb.Instance.Books.SingleOrDefault(item=>item.Id==id); + var tmpResult = tmp != null? new BookDto{ + Id = tmp.Id, + BooksName = tmp.BooksName, + Publiser = tmp.Publiser, + Price = tmp.Price, + AuthorId = tmp.AuthorId + }:null; + return tmpResult; +} +// 修改图书 +public BookDto? UpdateBook(Guid bookId,BookDtoUpdate bookDtoUpdate) +{ + var item = BookStoreDb.Instance.Books.SingleOrDefault(b=>b.Id==bookId); + if(item == null){ + return null; + } + item.BooksName = bookDtoUpdate.BooksName; + item.Publiser = bookDtoUpdate.Publiser; + item.Price = bookDtoUpdate.Price; + var res = new BookDto{ + Id=item.Id, + Publiser=item.Publiser, + Price=item.Price + }; + return res; +} +// 删除图书 +public string DelBook(Guid id) +{ + var book = BookStoreDb.Instance.Books.SingleOrDefault(b => b.Id==id); + if(book != null){ + BookStoreDb.Instance.Books.Remove(book); + return "删除成功"; + } + return "删除失败"; +} +``` +## 三、控制器操作 +```js +//------------------------------获取图书----------------------------- + [HttpGet("{bookId?}")] + public IActionResult Get(Guid authorId,Guid? bookId) + { + var author = AuthorRepository.GetAuthorById(authorId); + if (author == null) + { + return NotFound("未找到作者"); + } + + if (bookId.HasValue) + { + var book = BookRepository.GetBookById(bookId.Value); + if (book == null || book.AuthorId != authorId) + { + return NotFound("未找到该图书"); + } + return Ok(book); + } + else + { + var books = BookRepository.GetAllBooks(authorId); + return Ok(books); + } + } +//------------------------------添加图书----------------------------- + [HttpPost] + public IActionResult Post(Guid authorId,AddBookDto addBookDto) + { + var author = AuthorRepository.GetAuthorById(authorId); + if(author == null){ + return NotFound("未找到作者"); + } + var bookDto = BookRepository.AddBook(authorId, addBookDto); + return Ok(bookDto); + } +//------------------------------修改图书----------------------------- + [HttpPut("{bookId}")] + public IActionResult Put(Guid authorId,Guid bookId,BookDtoUpdate bookDtoUpdate) + { + var author = AuthorRepository.GetAuthorById(authorId); + if(author == null){ + return NotFound("未找到作者"); + } + var res = BookRepository.UpdateBook(bookId,bookDtoUpdate); + if(res == null){ + return Ok("修改失败"); + } + return Ok("修改成功"); + } +//------------------------------删除图书----------------------------- + [HttpDelete("{bookId}")] + public IActionResult Del(Guid authorId,Guid bookId) + { + var author = AuthorRepository.GetAuthorById(authorId); + if(author == null){ + return NotFound("未找到作者"); + } + var book = BookRepository.DelBook(bookId); + return Ok(book); + } +``` \ No newline at end of file diff --git "a/\347\274\252\346\242\223\344\272\250/20240606-EFCore\344\273\213\347\273\215.md" "b/\347\274\252\346\242\223\344\272\250/20240606-EFCore\344\273\213\347\273\215.md" new file mode 100644 index 0000000..6ac3902 --- /dev/null +++ "b/\347\274\252\346\242\223\344\272\250/20240606-EFCore\344\273\213\347\273\215.md" @@ -0,0 +1,65 @@ +## 一、EF Core的简介 + +### 1.概念 + +- EF Core(Entity Framework Core)是基于.NET Core的轻量级ORM框架 +- ORM能够处理数据库与高级编程语言中对象之间的映射关系 + +### 2. .NET对象与关系型数据库的对应关系 + +| .NET对象 | 关系型数据库 | +| :--------------: | :----------: | +| 类 | 表 | +| 类的属性或字段 | 表中的列 | +| 集合中的元素 | 表中的行 | +| 对于其他类的引用 | 外键 | + +### 3.支持LINQ(集成语言查询) + +#### 1.查询所有 + +```cs +var result = from item in collection + select item; +``` + +#### 2.过滤 + +```cs +var result = from item in collection + where price > 10 + select item; +``` + +#### 3.排序 + +```cs +var result = from item in collection + orderby item.Property ascending/descending + select item; +//ascending(升序,默认);descending(降序)关键字 +``` + +#### 4.连接查询 + +```cs +var query = from person in people + join address in addresses on person.AddressId equals address.Id + select new { person.Name, address.City }; + +``` + +## 二、在项目中添加EF Core + +### 1.安装包 + +```js +dotnet add package Microsoft.EntityFrameworkCore +``` + +### 2.安装提供程序 + +```js +//这里为SQL Server数据库为例 +dotnet add package Microsoft.EntityFrameworkCore.SqlServer +``` \ No newline at end of file diff --git "a/\347\274\252\346\242\223\344\272\250/20240607-EFcore\344\275\277\347\224\250.md" "b/\347\274\252\346\242\223\344\272\250/20240607-EFcore\344\275\277\347\224\250.md" new file mode 100644 index 0000000..44e2177 --- /dev/null +++ "b/\347\274\252\346\242\223\344\272\250/20240607-EFcore\344\275\277\347\224\250.md" @@ -0,0 +1,96 @@ +## 一、EF Core的两种使用方法 +### 1.代码优先(推荐) +- 根据先创建好的实体类来创建数据库和表 +- EF Core会将对实体类的修改同步到数据库中,都是对数据库手工修改将会在EF Core同步数据后丢失 +- 用于同步代码到数据库的方法是迁移(Migration),就是提供以增量的方式来修改数据库和表结构,使实体类和数据库保持一致 +### 2.数据库优先 +根据先创建好的数据库生成相应的代码 + +## 二、EF Core的添加步骤(代码优先) +### 1.创建数据模型 +创建数据模型类,这些类将映射到数据库中的表 + +### 2. 配置数据库连接 +```c# +// appsetting.json +"ConnectionString":{ + Mssql:"server=.;database=BookStore;uid=sa;pwd=123456;TrustServerCertificate=true;" +} +``` + +### 3.配置数据库上下文DbContext +- DbContext是非常重要的类,代表程序与数据库之间的会话或数据上下文,能够完成查询和保存数据等操作 +- 它的派生类中有若干个DbSet类型的公告属性,表示相应实体的集合,对它们的操作最后会反映到数据表 +```c# +// Db/BookStoreDbContext.cs +using Microsoft.EntityFrameworkCore; +namespace BookStore.Api.Db; +public class BookStoreDbContext:DbContext +{ + public DbSet Authors {get;set;} + public DbSet Books {get;set;} + // 构造函数接受一个 DbContextOptions 类型的参数 + // 将该参数传递给基类的构造函数 base(options) + // 这个构造函数用于配置数据库上下文的选项,例如数据库提供程序、连接字符串等 + public BookStoreDbContext(DbContextOptions options):base(options) + { + + } +} +``` +**注意点:** +- 提供正确的连接字符串 +- 必须构造函数选项配置 + +### 4.注入服务,引入配置文件,实现连接数据库 +```c# +// Startup.cs +servuces.AddDbContext(config => + config.UseSqlServer(Configuration.GetConnectionString("Mssql")); + // 也可以直接在GetConnectionString()里写连接字符串内容 +) +``` +**注意:** +这里UseSqlServer只有在Microsoft.EntityFrameworkcore.SqlServer包安装后才可以使用 + +### 5.生成迁移与创建数据库 +```js +// 安装dotnet-ef工具 +dotnet tool install -g dotnet-ef +// 生成迁移 +dotnet ef migrations add <迁移名称> +// 如果迁移成功就会出现Migrations文件夹 + +// 创建数据库(同步) + +dotnet ef database update +// 创建成功就会在数据库出现表,其中会自带一个名为_EFMigrationsHistory的表,这是存储迁移的历史记录,删除就会导致程序运行失败 +``` +**注意:** +- 迁移名称最好是英文且首字母大写 +- 使用迁移前需要安装Microsoft.EntityFrameworkcore +- 需要全局安装dotnet-ef工具 +- 代码不能有错误,否则迁移中会报错 + +### 6.添加种子数据 +#### 为种子数据建模 +```c# +// OnModelCreating.cs +protected override void OnModelCreating(ModelBuilder modelBuider) +{ + base.OnModelCreating(modelBuider); + modelBuilder.Entity().HasData(new Author{ + Id = new Guid, + AuthorName = "小米" + }, + new Author{ + ...... + } + ); + modelBuilder.Entity().HasData(new Book{......}); +} +// HasData方法可添加一个或多个相同的实体类型 +``` +**注意:** +1. 通常情况下数据库会自动生成主键值,但在种子数据中,您仍然需要为主键字段指定值 +2. 如果以任何方式更改主键,将删除之前设定种子的数据 -- Gitee