diff --git "a/\350\277\236\345\242\236\351\222\261/20240603_\350\267\257\347\224\261\346\216\245\345\217\243.md" "b/\350\277\236\345\242\236\351\222\261/20240603_\350\267\257\347\224\261\346\216\245\345\217\243.md" new file mode 100644 index 0000000000000000000000000000000000000000..1c7c7a780fc4467ca2cb734757de8f7b798933bc --- /dev/null +++ "b/\350\277\236\345\242\236\351\222\261/20240603_\350\267\257\347\224\261\346\216\245\345\217\243.md" @@ -0,0 +1,102 @@ +## 路由查询· +### 接口 +```C# + using BookStore.Api.Dto; + +namespace BookStore.Api.Interface; + +public interface IAuthorRepository +{ + // 通过Id获取指定作者的方法 + AuthorDto? GetAuthorById(Guid id); + + // 获取所有作者的方法 + // 函数三要素:函数名称、函数参数、函数返回值 + ICollection GetAllAuthors(); + + + AuthorDto Insert(AuthorCreateDto authorCreateDto); + +} +``` +### 实现 +```C# + public AuthorDto Insert(AuthorCreateDto authorCreateDto) + { + // 将传入的dto转换为保存到数据库需要的实体类型 + var author = new Authors + { + Id = Guid.NewGuid(), + AuthorName = authorCreateDto.AuthorName, + Gender = authorCreateDto.Gender, + Birthday = authorCreateDto.Birthday, + }; + // 插入数据库 + BookStoreDb.Instance.Authors.Add(author); + // 将内存数据库获取的数据转换为AuthorDto的实例 + var authorDto = new AuthorDto { Id = author.Id, AuthorName = author.AuthorName, Gender = author.Gender }; + return authorDto; + } + + public ICollection GetAllAuthors() + { + // 这个实现应该从持久化的数据源中获得:数据库、文件、各种异构数据、从各种api中获取的数据 + var list = BookStoreDb.Instance.Authors.ToList(); + var resultList = new List();// let resultList=[] + list.ForEach(item => + { + // 实例化一个对象这里有2种方式,一个是直接调用构造函数,形如:new AuthorDto() + // 另一个是直接填充其属性,形如:new AuthorDto{} + var tmp = new AuthorDto { Id = item.Id, AuthorName = item.AuthorName, Gender = item.Gender }; + resultList.Add(tmp); + }); + return resultList; + } + + public AuthorDto? GetAuthorById(Guid id) + { + var tmp = BookStoreDb.Instance.Authors.SingleOrDefault(item => item.Id == id); + var tmpResult = tmp != null ? new AuthorDto { Id = tmp.Id, AuthorName = tmp.AuthorName, Gender = tmp.Gender } : null; + // dynamic xResult=null; + // if(tmp!=null){ + // xResult=new AuthorDto { Id = tmp.Id, AuthorName = tmp.AuthorName, Gender = tmp.Gender }; + // } + return tmpResult; + } +``` +### action +```C# + [HttpGet("{id?}")] + public IActionResult Get(Guid id) + { + if (id.ToString() == "00000000-0000-0000-0000-000000000000") + { + return Ok(_authorRepository.GetAllAuthors()); + } + else + { + var item = _authorRepository.GetAuthorById(id); + return Ok(item); + } + } + + /// + /// 新增作者 + /// + /// 接受的参数 + /// + [HttpPost] + public IActionResult Post(AuthorCreateDto authorCreateDto) + { + /* + 1.拿到AuthorCreateDto类型的实例化数据-模型绑定 + 2.将相关数据保存到数据库 + 1.转换AuthorCreateDto类型的数据为Authors + 2.调用数据库上下文,将数据插入 + + */ + var result = _authorRepository.Insert(authorCreateDto); + return Ok(result); + } + +``` \ No newline at end of file diff --git "a/\350\277\236\345\242\236\351\222\261/20240604_\346\216\247\345\210\266\345\231\250\347\232\204\345\256\236\347\216\260.md" "b/\350\277\236\345\242\236\351\222\261/20240604_\346\216\247\345\210\266\345\231\250\347\232\204\345\256\236\347\216\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..3a6d81bad71cb4207914f52d3957f3ce71a3ba2f --- /dev/null +++ "b/\350\277\236\345\242\236\351\222\261/20240604_\346\216\247\345\210\266\345\231\250\347\232\204\345\256\236\347\216\260.md" @@ -0,0 +1,77 @@ +```js + [HttpGet("{id?}")] + public IActionResult Get(Guid id) + { + if (id.ToString() == "00000000-0000-0000-0000-000000000000") + { + return Ok(_authorRepository.GetAllAuthors()); + } + else + { + var item = _authorRepository.GetAuthorById(id); + return Ok(item); + } + } + + /// + /// 新增作者 + /// + /// 接受的参数 + /// + [HttpPost] + public IActionResult Post(AuthorCreateDto authorCreateDto) + { + /* + 1.拿到AuthorCreateDto类型的实例化数据-模型绑定 + 2.将相关数据保存到数据库 + 1.转换AuthorCreateDto类型的数据为Authors + 2.调用数据库上下文,将数据插入 + + */ + var result = _authorRepository.Insert(authorCreateDto); + return Ok(result); + } +``` + +```js + public AuthorDto Insert(AuthorCreateDto authorCreateDto) + { + // 将传入的dto转换为保存到数据库需要的实体类型 + var author = new Authors + { + Id = Guid.NewGuid(), + AuthorName = authorCreateDto.AuthorName, + Gender = authorCreateDto.Gender, + Birthday = authorCreateDto.Birthday, + }; + // 插入数据库 + BookStoreDb.Instance.Authors.Add(author); + // 将内存数据库获取的数据转换为AuthorDto的实例 + var authorDto = new AuthorDto { Id = author.Id, AuthorName = author.AuthorName, Gender = author.Gender }; + return authorDto; + } + + public ICollection GetAllAuthors() + { + // 这个实现应该从持久化的数据源中获得:数据库、文件、各种异构数据、从各种api中获取的数据 + var list = BookStoreDb.Instance.Authors.ToList(); + var resultList = new List();// let resultList=[] + list.ForEach(item => + { + // 实例化一个对象这里有2种方式,一个是直接调用构造函数,形如:new AuthorDto() + // 另一个是直接填充其属性,形如:new AuthorDto{} + var tmp = new AuthorDto { Id = item.Id, AuthorName = item.AuthorName, Gender = item.Gender }; + resultList.Add(tmp); + }); + return resultList; + } + + public AuthorDto? GetAuthorById(Guid id) + { + var tmp = BookStoreDb.Instance.Authors.SingleOrDefault(item => item.Id == id); + var tmpResult = tmp != null ? new AuthorDto { Id = tmp.Id, AuthorName = tmp.AuthorName, Gender = tmp.Gender } : null; + // dynamic xResult=null; + // if(tmp!=null){ + // xResult=new AuthorDto { Id = tmp.Id, AuthorName = tmp.AuthorName, Gender = tmp.Gender }; + // } +``` \ No newline at end of file diff --git "a/\350\277\236\345\242\236\351\222\261/20240606_EFCore\344\273\213\347\273\215.md" "b/\350\277\236\345\242\236\351\222\261/20240606_EFCore\344\273\213\347\273\215.md" new file mode 100644 index 0000000000000000000000000000000000000000..ea8544da0872313d1a690b2b7870582333bfb2b0 --- /dev/null +++ "b/\350\277\236\345\242\236\351\222\261/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.查询所有 + +~~~c# +var result = from item in collection + select item; +~~~ + +#### 2.过滤 + +~~~c# +var result = from item in collection + where price > 10 + select item; +~~~ + +#### 3.排序 + +~~~c# +var result = from item in collection + orderby item.Property ascending/descending + select item; +//ascending(升序,默认);descending(降序)关键字 +~~~ + +#### 4.连接查询 + +~~~c# +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/\350\277\236\345\242\236\351\222\261/20240607_EFCore\347\232\204\344\275\277\347\224\250.md" "b/\350\277\236\345\242\236\351\222\261/20240607_EFCore\347\232\204\344\275\277\347\224\250.md" new file mode 100644 index 0000000000000000000000000000000000000000..15ed5f7ef24a16d9c18951d9a33641fd56db22c3 --- /dev/null +++ "b/\350\277\236\345\242\236\351\222\261/20240607_EFCore\347\232\204\344\275\277\347\224\250.md" @@ -0,0 +1,134 @@ +## 一、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. 如果以任何方式更改主键,将删除之前设定种子的数据 +#### 方法二--手动迁移自定义 +解决 HasData 的某些限制的方法之一是改为手动向迁移添加这些调用或自定义操作 +~~~c# +// 在Migrations目录下以_SeeData.cs结尾的文件中,包含两个方法Up和Down +//在Up方法中调用迁移生成器对象的InsertData方法 +migrationBuilder.InsertData( + table: "Authors", //目标表的名称 + columns: new[] { "Url" }, //目标表的名称 + values: new object[] { "http://generated.com" } //要插入列的值 +); +// 如果要给全部列插入数据,则直接省略columns 参数 +// 直接提供 values 参数中与表中列顺序相对应的数值 +~~~ + +#### 方法三--自定义初始化逻辑 +在主应用程序逻辑开始执行之前使用 DbContext.SaveChanges()执行数据种子设定 +~~~c# +//program.cs +public static void Main(string[] args) +{ + var app = CreateHostBuilder(args).Build(); + + // 在应用程序启动时执行数据种子逻辑 + using (var context = new DataSeedingContext()) + { + context.Database.EnsureCreated(); + // 检查是否存在该数据信息,若不存在则添加该数据 + var testBlog = context.Authors.FirstOrDefault(a => a.AuthorName == "小明"); + if (testBlog == null) + { + context.Authors.Add(new Author { AuthorName == "小明" }); + } + + context.SaveChanges(); + } + app.Run(); +} +~~~ \ No newline at end of file