From 3f98f8b039f73021056fb8f0e251040705031d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=99=E6=A2=A6=E5=A9=B7?= <3410849650@qq.com> Date: Sun, 9 Jun 2024 22:21:02 +0800 Subject: [PATCH] 69 --- ...3-\344\270\255\351\227\264\344\273\266.md" | 88 ++++ .../20240604-MVC.md" | 318 ++++++++++++++ ...40\346\224\271\346\237\245\357\274\211.md" | 374 +++++++++++++++++ .../20240607-Entity Framework Core.md" | 397 ++++++++++++++++++ 4 files changed, 1177 insertions(+) create mode 100644 "\344\275\231\346\242\246\345\251\267/20240603-\344\270\255\351\227\264\344\273\266.md" create mode 100644 "\344\275\231\346\242\246\345\251\267/20240604-MVC.md" create mode 100644 "\344\275\231\346\242\246\345\251\267/20240606-\350\265\204\346\272\220\346\223\215\344\275\234\357\274\210\345\242\236\345\210\240\346\224\271\346\237\245\357\274\211.md" create mode 100644 "\344\275\231\346\242\246\345\251\267/20240607-Entity Framework Core.md" diff --git "a/\344\275\231\346\242\246\345\251\267/20240603-\344\270\255\351\227\264\344\273\266.md" "b/\344\275\231\346\242\246\345\251\267/20240603-\344\270\255\351\227\264\344\273\266.md" new file mode 100644 index 0000000..8877714 --- /dev/null +++ "b/\344\275\231\346\242\246\345\251\267/20240603-\344\270\255\351\227\264\344\273\266.md" @@ -0,0 +1,88 @@ +#### 1. 什么是中间件? + +中间件是 ASP.NET Core 请求处理管道中的组件,它们能够处理请求、响应或修改它们。每个中间件组件在管道中执行特定的任务,可以组合使用以构建功能丰富的应用程序。 + +#### 2. ASP.NET Core 请求处理管道 + +ASP.NET Core 的请求处理管道是一系列中间件的组合,用于处理传入请求并生成响应。管道由一系列中间件组成,它们按顺序执行,每个中间件可以选择终止请求管道或将其传递给下一个中间件。 + +#### 3. 编写自定义中间件 + +##### 3.1. 创建中间件类 + +```csharp +public class CustomMiddleware +{ + private readonly RequestDelegate _next; + + public CustomMiddleware(RequestDelegate next) + { + _next = next; + } + + public async Task InvokeAsync(HttpContext context) + { + // 中间件逻辑 + await _next(context); + } +} +``` + +##### 3.2. 注册中间件 + +在 `Startup.cs` 中的 `Configure` 方法中使用 `app.UseMiddleware();` 注册自定义中间件。 + +```csharp +public void Configure(IApplicationBuilder app, IWebHostEnvironment env) +{ + // 其他配置 + app.UseMiddleware(); + // 其他中间件 +} +``` + +#### 4. 内置中间件 + +ASP.NET Core 提供了一些内置的中间件,用于处理常见的任务,例如路由、身份验证和静态文件服务。 + +##### 4.1. 静态文件中间件 + +静态文件中间件用于提供静态文件,例如 HTML、CSS、JavaScript 和图像。它允许直接从文件系统提供这些文件,而不需要经过控制器。 + +```csharp +app.UseStaticFiles(); +``` + +##### 4.2. 路由中间件 + +路由中间件根据 URL 将请求路由到相应的端点。它负责确定如何响应传入请求,通常与 MVC 或 Web API 一起使用。 + +```csharp +app.UseRouting(); +``` + +#### 5. 中间件执行顺序 + +中间件按照它们在管道中注册的顺序执行。注册在 `Configure` 方法中靠前的中间件先执行,后注册的中间件后执行。这一顺序非常重要,因为中间件的执行顺序可能会影响应用程序的行为。 + +#### 6. 中间件执行流程图 + +```plantuml +@startuml +client -> ASP.NET Core: 发送请求 +ASP.NET Core -> Middleware1: 执行中间件1 +Middleware1 -> Middleware2: 转发请求 +Middleware2 -> Middleware3: 转发请求 +Middleware3 -> Application: 最终处理请求 +Application -> Middleware3: 发送响应 +Middleware3 -> Middleware2: 返回响应 +Middleware2 -> Middleware1: 返回响应 +Middleware1 -> client: 返回响应 +@enduml +``` + +#### 7. 注意事项 + +- **顺序重要性**:注册中间件的顺序决定了它们的执行顺序。 +- **中间件责任**:每个中间件应只负责一个具体的任务,避免过多的逻辑集中在一个中间件中。 +- **异常处理**:确保中间件能够适当地处理异常情况,不影响整个应用程序的稳定性。 \ No newline at end of file diff --git "a/\344\275\231\346\242\246\345\251\267/20240604-MVC.md" "b/\344\275\231\346\242\246\345\251\267/20240604-MVC.md" new file mode 100644 index 0000000..d1f12da --- /dev/null +++ "b/\344\275\231\346\242\246\345\251\267/20240604-MVC.md" @@ -0,0 +1,318 @@ +## ASP.NET Core 简介 + +ASP.NET Core 是一个开源、跨平台的框架,主要用于构建现代、基于云的 Web 应用程序。它是 ASP.NET 的重新设计版本,具有更好的性能、灵活性和可扩展性。 + +**特点**: + +- **跨平台**:支持 Windows、macOS 和 Linux。 +- **高性能**:在许多基准测试中表现出色。 +- **统一的编程模型**:整合了 MVC 和 Web API。 + +## MVC 架构 + +MVC 架构将应用程序分为三个主要组件:Model、View 和 Controller,每个组件负责不同的任务。 + +### Model + +Model 代表应用程序的核心数据和业务逻辑。它负责处理数据的获取、存储和验证。 + +**关键概念**: + +- **实体类**:表示数据结构。 +- **数据上下文(DbContext)**:管理数据访问。 +- **数据注解(Data Annotations)**:用于数据验证。 + +```csharp +public class Product +{ + public int Id { get; set; } + public string Name { get; set; } + [Required] + public decimal Price { get; set; } +} +``` + +### View + +View 负责显示用户界面。它通常是 HTML 页面,使用 Razor 语法生成动态内容。 + +**关键概念**: + +- **Razor 视图引擎**:用于生成动态 HTML 内容。 +- **视图模型(ViewModel)**:用于传递数据到视图。 + +```html +@model Product + +

@Model.Name

+

Price: @Model.Price

+``` + +### Controller + +Controller 处理用户请求,协调 Model 和 View。它接收输入、调用 Model 进行处理,并返回 View 显示结果。 + +**关键概念**: + +- **动作方法(Action Methods)**:处理请求并返回结果。 +- **返回类型**:可以是 ViewResult、JsonResult 等。 + +```csharp +public class ProductController : Controller +{ + private readonly ApplicationDbContext _context; + + public ProductController(ApplicationDbContext context) + { + _context = context; + } + + public IActionResult Index() + { + var products = _context.Products.ToList(); + return View(products); + } +} +``` + +## 项目结构 + +ASP.NET Core MVC 项目包含多个文件和文件夹,每个部分有特定的作用。 + +``` +├── Controllers +│ └── HomeController.cs +├── Models +│ └── Product.cs +├── Views +│ ├── Home +│ │ └── Index.cshtml +├── wwwroot +│ └── css +│ └── site.css +├── appsettings.json +├── Program.cs +└── Startup.cs +``` + +**关键文件**: + +- **Controllers**:包含控制器。 +- **Models**:包含模型。 +- **Views**:包含视图。 +- **wwwroot**:静态文件目录。 +- **Startup.cs**:配置应用程序服务和中间件。 + +## 路由(Routing) + +路由定义了 URL 路径与控制器和动作方法之间的映射关系。 + +### 默认路由 + +默认路由通常在 `Startup.cs` 中配置: + +```csharp +app.UseEndpoints(endpoints => +{ + endpoints.MapControllerRoute( + name: "default", + pattern: "{controller=Home}/{action=Index}/{id?}"); +}); +``` + +### 属性路由 + +属性路由通过在控制器和动作方法上使用属性进行配置: + +```csharp +[Route("products")] +public class ProductController : Controller +{ + [Route("")] + public IActionResult Index() + { + // ... + } + + [Route("{id}")] + public IActionResult Details(int id) + { + // ... + } +} +``` + +## 依赖注入(Dependency Injection) + +ASP.NET Core 内置支持依赖注入,方便管理对象的生命周期和依赖关系。 + +### 注册服务 + +在 `Startup.cs` 中配置依赖注入: + +```csharp +public void ConfigureServices(IServiceCollection services) +{ + services.AddDbContext(options => + options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); + services.AddScoped(); + services.AddControllersWithViews(); +} +``` + +### 使用服务 + +通过构造函数注入使用服务: + +```csharp +public class ProductController : Controller +{ + private readonly IProductService _productService; + + public ProductController(IProductService productService) + { + _productService = productService; + } + + // ... +} +``` + +## 中间件(Middleware) + +中间件是处理 HTTP 请求和响应的组件,按管道顺序执行。 + +### 常见中间件 + +- **Authentication**:认证 +- **Authorization**:授权 +- **StaticFiles**:处理静态文件 +- **Routing**:路由 + +### 配置中间件 + +在 `Startup.cs` 中配置中间件: + +```csharp +public void Configure(IApplicationBuilder app, IWebHostEnvironment env) +{ + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else + { + app.UseExceptionHandler("/Home/Error"); + app.UseHsts(); + } + + app.UseHttpsRedirection(); + app.UseStaticFiles(); + + app.UseRouting(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllerRoute( + name: "default", + pattern: "{controller=Home}/{action=Index}/{id?}"); + }); +} +``` + +## 示例项目 + +下面是一个简单的 ASP.NET Core MVC 项目示例,包含一个产品列表页面。 + +### 步骤 1:创建模型 + +```csharp +public class Product +{ + public int Id { get; set; } + public string Name { get; set; } + public decimal Price { get; set; } +} +``` + +### 步骤 2:创建数据库上下文 + +```csharp +public class ApplicationDbContext : DbContext +{ + public ApplicationDbContext(DbContextOptions options) + : base(options) + { + } + + public DbSet Products { get; set; } +} +``` + +### 步骤 3:创建控制器 + +```csharp +public class ProductController : Controller +{ + private readonly ApplicationDbContext _context; + + public ProductController(ApplicationDbContext context) + { + _context = context; + } + + public IActionResult Index() + { + var products = _context.Products.ToList(); + return View(products); + } +} +``` + +### 步骤 4:创建视图 + +在 `Views/Product/Index.cshtml` 中: + +```html +@model IEnumerable + +

Product List

+ + + + + + + + + @foreach (var product in Model) + { + + + + + } + +
NamePrice
@product.Name@product.Price
+``` + +### 步骤 5:配置路由和中间件 + +在 `Startup.cs` 中: + +```csharp +public void Configure(IApplicationBuilder app, IWebHostEnvironment env) +{ + // 其他配置... + + app.UseEndpoints(endpoints => + { + endpoints.MapControllerRoute( + name: "default", + pattern: "{controller=Product}/{action=Index}/{id?}"); + }); +} +``` \ No newline at end of file diff --git "a/\344\275\231\346\242\246\345\251\267/20240606-\350\265\204\346\272\220\346\223\215\344\275\234\357\274\210\345\242\236\345\210\240\346\224\271\346\237\245\357\274\211.md" "b/\344\275\231\346\242\246\345\251\267/20240606-\350\265\204\346\272\220\346\223\215\344\275\234\357\274\210\345\242\236\345\210\240\346\224\271\346\237\245\357\274\211.md" new file mode 100644 index 0000000..ac179da --- /dev/null +++ "b/\344\275\231\346\242\246\345\251\267/20240606-\350\265\204\346\272\220\346\223\215\344\275\234\357\274\210\345\242\236\345\210\240\346\224\271\346\237\245\357\274\211.md" @@ -0,0 +1,374 @@ +## 资源操作简介 + +在 ASP.NET Core 中,资源操作通常通过控制器方法实现,控制器方法调用 EF Core 进行数据库操作。以下是基本的 CRUD 操作: + +1. **创建(Create)**:添加新资源。 +2. **读取(Read)**:获取资源列表或单个资源。 +3. **更新(Update)**:修改现有资源。 +4. **删除(Delete)**:移除资源。 + +## 创建资源 + +创建资源通常通过 POST 请求实现。以下是示例代码: + +### 控制器方法 + +```csharp +[HttpPost] +public async Task Create([FromBody] Product product) +{ + if (ModelState.IsValid) + { + _context.Products.Add(product); + await _context.SaveChangesAsync(); + return CreatedAtAction(nameof(GetById), new { id = product.Id }, product); + } + return BadRequest(ModelState); +} +``` + +### 请求示例 + +```json +POST /api/products +{ + "name": "New Product", + "price": 19.99 +} +``` + +### 说明 + +- 使用 `[FromBody]` 属性从请求主体中获取数据。 +- 调用 `CreatedAtAction` 方法返回创建的资源和状态码 201。 + +## 读取资源 + +读取资源包括获取资源列表和单个资源,通常通过 GET 请求实现。 + +### 获取资源列表 + +```csharp +[HttpGet] +public async Task>> GetAll() +{ + return await _context.Products.ToListAsync(); +} +``` + +### 获取单个资源 + +```csharp +[HttpGet("{id}")] +public async Task> GetById(int id) +{ + var product = await _context.Products.FindAsync(id); + if (product == null) + { + return NotFound(); + } + return product; +} +``` + +### 请求示例 + +```http +GET /api/products +GET /api/products/1 +``` + +### 说明 + +- `GetAll` 方法返回所有资源。 +- `GetById` 方法根据 ID 返回单个资源,如果找不到则返回 404。 + +## 更新资源 + +更新资源通常通过 PUT 或 PATCH 请求实现。 + +### 控制器方法 + +```csharp +[HttpPut("{id}")] +public async Task Update(int id, [FromBody] Product product) +{ + if (id != product.Id) + { + return BadRequest(); + } + + _context.Entry(product).State = EntityState.Modified; + + try + { + await _context.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!_context.Products.Any(e => e.Id == id)) + { + return NotFound(); + } + else + { + throw; + } + } + + return NoContent(); +} +``` + +### 请求示例 + +```json +PUT /api/products/1 +{ + "id": 1, + "name": "Updated Product", + "price": 29.99 +} +``` + +### 说明 + +- 使用 `EntityState.Modified` 标记资源为已修改。 +- 处理并发更新异常,确保资源存在。 + +## 删除资源 + +删除资源通常通过 DELETE 请求实现。 + +### 控制器方法 + +```csharp +[HttpDelete("{id}")] +public async Task Delete(int id) +{ + var product = await _context.Products.FindAsync(id); + if (product == null) + { + return NotFound(); + } + + _context.Products.Remove(product); + await _context.SaveChangesAsync(); + + return NoContent(); +} +``` + +### 请求示例 + +```http +DELETE /api/products/1 +``` + +### 说明 + +- 使用 `Remove` 方法删除资源。 +- 如果资源不存在,返回 404。 + +## 补充说明和注解 + +### 模型验证 + +在处理请求时,通常会进行模型验证,以确保数据有效。ASP.NET Core 提供了丰富的数据注解,用于验证模型属性。 + +```csharp +public class Product +{ + public int Id { get; set; } + + [Required] + public string Name { get; set; } + + [Range(0.01, 1000.00)] + public decimal Price { get; set; } +} +``` + +### 异步操作 + +EF Core 支持异步操作,使用 `async` 和 `await` 关键字可以提高应用程序的性能,特别是在处理 I/O 密集型任务时。 + +### 错误处理 + +良好的错误处理机制可以提高应用的健壮性。在控制器方法中,可以使用 `try-catch` 块捕获异常,并返回适当的 HTTP 状态码。 + +## 示例项目 + +### 项目结构 + +``` +├── Controllers +│ └── ProductController.cs +├── Models +│ └── Product.cs +├── Data +│ └── ApplicationDbContext.cs +├── Program.cs +└── Startup.cs +``` + +### 创建模型 + +```csharp +public class Product +{ + public int Id { get; set; } + + [Required] + public string Name { get; set; } + + [Range(0.01, 1000.00)] + public decimal Price { get; set; } +} +``` + +### 配置数据库上下文 + +```csharp +public class ApplicationDbContext : DbContext +{ + public ApplicationDbContext(DbContextOptions options) + : base(options) + { + } + + public DbSet Products { get; set; } +} +``` + +### 配置依赖注入 + +在 `Startup.cs` 中配置依赖注入: + +```csharp +public void ConfigureServices(IServiceCollection services) +{ + services.AddDbContext(options => + options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); + services.AddControllers(); +} +``` + +### 创建控制器 + +```csharp +[Route("api/[controller]")] +[ApiController] +public class ProductController : ControllerBase +{ + private readonly ApplicationDbContext _context; + + public ProductController(ApplicationDbContext context) + { + _context = context; + } + + // Create + [HttpPost] + public async Task Create([FromBody] Product product) + { + if (ModelState.IsValid) + { + _context.Products.Add(product); + await _context.SaveChangesAsync(); + return CreatedAtAction(nameof(GetById), new { id = product.Id }, product); + } + return BadRequest(ModelState); + } + + // Read All + [HttpGet] + public async Task>> GetAll() + { + return await _context.Products.ToListAsync(); + } + + // Read Single + [HttpGet("{id}")] + public async Task> GetById(int id) + { + var product = await _context.Products.FindAsync(id); + if (product == null) + { + return NotFound(); + } + return product; + } + + // Update + [HttpPut("{id}")] + public async Task Update(int id, [FromBody] Product product) + { + if (id != product.Id) + { + return BadRequest(); + } + + _context.Entry(product).State = EntityState.Modified; + + try + { + await _context.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!_context.Products.Any(e => e.Id == id)) + { + return NotFound(); + } + else + { + throw; + } + } + + return NoContent(); + } + + // Delete + [HttpDelete("{id}")] + public async Task Delete(int id) + { + var product = await _context.Products.FindAsync(id); + if (product == null) + { + return NotFound(); + } + + _context.Products.Remove(product); + await _context.SaveChangesAsync(); + + return NoContent(); + } +} +``` + +### 配置路由和中间件 + +在 `Startup.cs` 中配置中间件和路由: + +```csharp +public void Configure(IApplicationBuilder app, IWebHostEnvironment env) +{ + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseHttpsRedirection(); + + app.UseRouting(); + + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); +} +``` \ No newline at end of file diff --git "a/\344\275\231\346\242\246\345\251\267/20240607-Entity Framework Core.md" "b/\344\275\231\346\242\246\345\251\267/20240607-Entity Framework Core.md" new file mode 100644 index 0000000..1f81282 --- /dev/null +++ "b/\344\275\231\346\242\246\345\251\267/20240607-Entity Framework Core.md" @@ -0,0 +1,397 @@ +## Entity Framework Core 简介 + +**Entity Framework Core** 是一个面向对象的关系映射(ORM)框架,提供了开发人员使用 .NET 对象与数据库交互的能力。EF Core 支持多种数据库提供程序,如 SQL Server、SQLite、MySQL 等。 + +**特点**: + +- **跨平台**:支持 Windows、macOS 和 Linux。 +- **高性能**:比 EF6 更轻量和高效。 +- **灵活**:支持代码优先和数据库优先的开发模式。 + +## 安装与配置 + +### 安装 EF Core 包 + +在项目中安装 EF Core 及其数据库提供程序(以 SQL Server 为例): + +```sh +dotnet add package Microsoft.EntityFrameworkCore +dotnet add package Microsoft.EntityFrameworkCore.SqlServer +``` + +### 配置数据库上下文 + +在 `Startup.cs` 中配置数据库上下文: + +```csharp +public void ConfigureServices(IServiceCollection services) +{ + services.AddDbContext(options => + options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); + services.AddControllers(); +} +``` + +在 `appsettings.json` 中添加连接字符串: + +```json +{ + "ConnectionStrings": { + "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MyDatabase;Trusted_Connection=True;" + } +} +``` + +## 数据模型 + +定义实体类来表示数据库表。以下是一个简单的 `Product` 实体类示例: + +```csharp +public class Product +{ + public int Id { get; set; } + public string Name { get; set; } + public decimal Price { get; set; } +} +``` + +## 数据库上下文 + +数据库上下文类继承自 `DbContext`,并包含 `DbSet` 属性来表示数据库表。 + +```csharp +public class ApplicationDbContext : DbContext +{ + public ApplicationDbContext(DbContextOptions options) + : base(options) + { + } + + public DbSet Products { get; set; } +} +``` + +## 基本 CRUD 操作 + +### 创建(Create) + +```csharp +public async Task Create(Product product) +{ + _context.Products.Add(product); + await _context.SaveChangesAsync(); + return CreatedAtAction(nameof(GetById), new { id = product.Id }, product); +} +``` + +### 读取(Read) + +#### 获取所有记录 + +```csharp +public async Task>> GetAll() +{ + return await _context.Products.ToListAsync(); +} +``` + +#### 根据 ID 获取记录 + +```csharp +public async Task> GetById(int id) +{ + var product = await _context.Products.FindAsync(id); + if (product == null) + { + return NotFound(); + } + return product; +} +``` + +### 更新(Update) + +```csharp +public async Task Update(int id, Product product) +{ + if (id != product.Id) + { + return BadRequest(); + } + + _context.Entry(product).State = EntityState.Modified; + await _context.SaveChangesAsync(); + + return NoContent(); +} +``` + +### 删除(Delete) + +```csharp +public async Task Delete(int id) +{ + var product = await _context.Products.FindAsync(id); + if (product == null) + { + return NotFound(); + } + + _context.Products.Remove(product); + await _context.SaveChangesAsync(); + + return NoContent(); +} +``` + +## 数据迁移 + +EF Core 提供数据迁移功能,用于创建和更新数据库结构。 + +### 添加迁移 + +```sh +dotnet ef migrations add InitialCreate +``` + +### 更新数据库 + +```sh +dotnet ef database update +``` + +## 高级主题 + +### 关系和导航属性 + +EF Core 支持多种关系类型:一对多、多对多和一对一。 + +#### 一对多关系示例 + +```csharp +public class Category +{ + public int Id { get; set; } + public string Name { get; set; } + public ICollection Products { get; set; } +} + +public class Product +{ + public int Id { get; set; } + public string Name { get; set; } + public decimal Price { get; set; } + public int CategoryId { get; set; } + public Category Category { get; set; } +} +``` + +### LINQ 查询 + +EF Core 支持使用 LINQ 进行查询。 + +#### 示例查询 + +```csharp +var expensiveProducts = await _context.Products + .Where(p => p.Price > 100) + .ToListAsync(); +``` + +### 延迟加载与急切加载 + +#### 延迟加载 + +延迟加载(Lazy Loading)在访问导航属性时才加载相关数据。 + +```csharp +public class ApplicationDbContext : DbContext +{ + public ApplicationDbContext(DbContextOptions options) + : base(options) + { + this.ChangeTracker.LazyLoadingEnabled = true; + } + + public DbSet Products { get; set; } + public DbSet Categories { get; set; } +} +``` + +#### 急切加载 + +急切加载(Eager Loading)在查询时使用 `Include` 方法加载相关数据。 + +```csharp +var productsWithCategories = await _context.Products + .Include(p => p.Category) + .ToListAsync(); +``` + +## 示例项目 + +### 项目结构 + +``` +├── Controllers +│ └── ProductController.cs +├── Models +│ └── Product.cs +│ └── Category.cs +├── Data +│ └── ApplicationDbContext.cs +├── Program.cs +└── Startup.cs +``` + +### 创建数据模型 + +```csharp +public class Product +{ + public int Id { get; set; } + public string Name { get; set; } + public decimal Price { get; set; } + public int CategoryId { get; set; } + public Category Category { get; set; } +} + +public class Category +{ + public int Id { get; set; } + public string Name { get; set; } + public ICollection Products { get; set; } +} +``` + +### 配置数据库上下文 + +```csharp +public class ApplicationDbContext : DbContext +{ + public ApplicationDbContext(DbContextOptions options) + : base(options) + { + } + + public DbSet Products { get; set; } + public DbSet Categories { get; set; } +} +``` + +### 配置依赖注入 + +在 `Startup.cs` 中配置依赖注入: + +```csharp +public void ConfigureServices(IServiceCollection services) +{ + services.AddDbContext(options => + options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); + services.AddControllers(); +} +``` + +### 创建控制器 + +```csharp +[Route("api/[controller]")] +[ApiController] +public class ProductController : ControllerBase +{ + private readonly ApplicationDbContext _context; + + public ProductController(ApplicationDbContext context) + { + _context = context; + } + + [HttpPost] + public async Task Create(Product product) + { + _context.Products.Add(product); + await _context.SaveChangesAsync(); + return CreatedAtAction(nameof(GetById), new { id = product.Id }, product); + } + + [HttpGet] + public async Task>> GetAll() + { + return await _context.Products.Include(p => p.Category).ToListAsync(); + } + + [HttpGet("{id}")] + public async Task> GetById(int id) + { + var product = await _context.Products.Include(p => p.Category).FirstOrDefaultAsync(p => p.Id == id); + if (product == null) + { + return NotFound(); + } + return product; + } + + [HttpPut("{id}")] + public async Task Update(int id, Product product) + { + if (id != product.Id) + { + return BadRequest(); + } + + _context.Entry(product).State = EntityState.Modified; + await _context.SaveChangesAsync(); + + return NoContent(); + } + + [HttpDelete("{id}")] + public async Task Delete(int id) + { + var product = await _context.Products.FindAsync(id); + if (product == null) + { + return NotFound(); + } + + _context.Products.Remove + +(product); + await _context.SaveChangesAsync(); + + return NoContent(); + } +} +``` + +### 配置路由和中间件 + +在 `Startup.cs` 中配置中间件和路由: + +```csharp +public void Configure(IApplicationBuilder app, IWebHostEnvironment env) +{ + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseHttpsRedirection(); + + app.UseRouting(); + + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); +} +``` + +## 补充说明和注解 + +1. **连接字符串安全性**:在生产环境中,避免将数据库连接字符串明文存储在 `appsettings.json` 文件中。建议使用环境变量或 Azure Key Vault 等安全存储方式。 +2. **数据库上下文生命周期**:确保数据库上下文的生命周期与请求的生命周期相同。推荐使用依赖注入的 `AddDbContext` 方法。 +3. **性能优化**:在大数据量操作时,考虑使用分页、批量操作和数据库索引来优化性能。 +4. **迁移管理**:定期备份数据库,并在应用迁移前测试迁移脚本,以防止数据丢失或损坏。 \ No newline at end of file -- Gitee