深入了解 .NET 8.0:新特性与开发最佳实践(微服务架构实践、Dapper 和 NLog 优化 .NET 应用程序的数据库操作与日志管理、控制反转与依赖注入:提升 .NET 应用程序的可维护性)
HTTP:适合需要实时交互的场景,通过 RESTful API 或 gRPC 进行服务调用。消息队列/Kafka:适合异步处理的场景,服务通过发布/订阅模型进行通信,解耦服务之间的依赖。Entity Framework Core(EF Core)是 Microsoft 开发的一个轻量级、跨平台的对象关系映射(ORM)框架,旨在简化 .NET 应用程序与数据库之间的交互。EF Core 允许开发者使
目录
2. ASP.NET 和 ASP.NET Core 的基本概念
4. 举例说明ASP.NET Core Web API 和ASP.NET Core MVC
8.Entity Framework Core(EF Core)
1、.NET8.0
.NET 8.0 是 Microsoft 发布的最新版本的跨平台开发框架,旨在支持构建现代应用程序,包括 web、桌面和云应用。它在之前版本的基础上进行了多项改进和优化,主要特点包括:
-
跨平台支持:允许开发者在 Windows、Linux 和 macOS 上构建和运行应用程序。
-
性能提升:引入了许多性能优化,提升应用的运行速度和响应能力。
-
统一的 API:进一步整合 .NET 生态系统,减少不同 .NET 版本间的差异。
-
新特性:与 C# 12 结合,增加了一些新的语法特性,提升开发效率。
-
更好的云集成:增强与 Azure 等云服务的集成,简化云原生应用的构建。
总体而言,.NET 8.0 为开发者提供了更强大的工具和功能,以支持现代应用开发。
2. ASP.NET 和 ASP.NET Core 的基本概念
-
ASP.NET:是微软开发的一个用于构建动态 Web 应用程序和服务的框架。它允许开发人员使用 C# 或其他 .NET 语言编写 Web 应用程序。ASP.NET 运行在 Windows 平台上,是过去广泛使用的框架。
-
ASP.NET Core:是 ASP.NET 的重新设计和升级版本,它是跨平台的(可以在 Windows、Linux 和 macOS 上运行),开源,并且比传统的 ASP.NET 更轻量级和高性能。ASP.NET Core 是用于现代 Web 开发的一个强大工具,适用于创建 Web 应用程序、RESTful API、微服务等。
3. ASP.NET 与 ASP.NET Core 的区别
-
ASP.NET:依赖于 .NET Framework,通常只能在 Windows 上运行。
-
ASP.NET Core:依赖于 .NET Core(现在已统一为 .NET 6+),可以跨平台运行,并且性能更优。
4. 举例说明ASP.NET Core Web API 和ASP.NET Core MVC
示例 1: ASP.NET Core Web API 示例
这是一个简单的 ASP.NET Core Web API 项目,处理 API 请求并返回 JSON 数据:
using Microsoft.AspNetCore.Mvc; namespace WebApiExample.Controllers { [ApiController] // 声明这是一个 Web API 控制器 [Route("api/[controller]")] // 定义路由为 api/values public class ValuesController : ControllerBase { // GET api/values [HttpGet] public ActionResult<IEnumerable<string>> Get() { return new string[] { "value1", "value2" }; // 返回 JSON 数据 } // GET api/values/5 [HttpGet("{id}")] public ActionResult<string> Get(int id) { return "value " + id; // 根据 ID 返回具体的数据 } // POST api/values [HttpPost] public void Post([FromBody] string value) { // 接收 POST 请求中的数据 } // PUT api/values/5 [HttpPut("{id}")] public void Put(int id, [FromBody] string value) { // 更新资源 } // DELETE api/values/5 [HttpDelete("{id}")] public void Delete(int id) { // 删除资源 } } }
这个例子展示了一个基本的 Web API:
-
GET
请求返回一个字符串数组,作为 JSON 响应。 -
POST
、PUT
、DELETE
允许你发送数据到服务器,或者更新/删除数据。
示例 2: ASP.NET Core MVC 示例
这是一个简单的 ASP.NET Core MVC 示例,返回 HTML 视图:
using Microsoft.AspNetCore.Mvc; //校车消息推送 [MobileAuthorize] public ActionResult SchoolBusNotice(int id) { var UserId = this.User.UserId;//(用户登录后 会有自己的userID) var model = App.DataAccess.GetSchoolBusNoticeInfo(id, UserId); //更新阅读时间和已读状态 App.DataAccess.UpdateNotificationReadStatus(id, UserId); return View(model); }
这是一个控制器动作,用于处理前端请求。
当用户访问/SchoolBusNotice/3 时候,执行一些逻辑操作(如获取数据、更新已读状态),然后返回HTML页面或视图给用户。常见于传统的Web应用程序(例如ASP.NET Core MVC),而不是用于返回JSON数据的API接口。开发接口用的框架是ASP.NET Core Web API
ASP.NET MVC中的控制器方法(ActionResult
)用于处理HTTP请求并返回视图(View
),这种架构属于**B/S架构
-
B/S架构是指客户端通过浏览器向服务器发送请求,服务器处理请求后,将页面(HTML、CSS、JavaScript等)返回给浏览器,浏览器负责渲染和展示内容。ASP.NET MVC正是这种典型的Web应用开发模式。浏览器是客户端,服务器是运行ASP.NET MVC应用的主机,二者通过HTTP通信。
-
在ASP.NET MVC中,用户通过浏览器访问某个URL,发送请求到服务器,服务器的控制器方法(例如上述代码中的的
SchoolBusNotice
方法)会处理请求、获取数据,并生成视图(View
),最终将视图渲染为HTML页面返回给浏览器进行显示。
C/S架构与B/S架构的区别:
-
C/S架构(Client/Server)是指客户端和服务器直接通信,客户端通常是一个独立的软件应用程序(如桌面程序)。客户端负责更多的业务逻辑和处理,通常需要安装在用户的本地设备上,而服务器提供后台数据和服务支持。
-
B/S架构更轻量化,客户端只需要浏览器,不需要安装额外的软件,所有的业务逻辑和处理大部分都在服务器端完成,用户通过浏览器即可访问应用程序。
5.在ASP.NET Core 中开发微服务
在 ASP.NET Core 中开发微服务是一种常见的架构实践,微服务架构将应用程序分解为多个独立的服务,每个服务执行特定的功能,彼此可以通过 API 通信。ASP.NET Core 是一个轻量级、高性能的框架,非常适合用于开发微服务。
(1)微服务架构的核心概念
-
每个微服务独立部署:每个微服务都可以独立构建、部署和扩展。
-
单一职责原则:每个微服务只负责一组相关的业务功能。
-
跨服务通信:服务间通过 HTTP、gRPC 或消息队列通信(如 RabbitMQ、Kafka)。
-
容错和扩展性:通过容器化(Docker、Kubernetes)来提高可扩展性和容错性。
(2)ASP.NET Core 微服务开发步骤
以下是开发微服务的一般步骤:
1.1 创建微服务项目
创建一个 ASP.NET Core 项目,每个项目对应一个独立的微服务。可以使用以下命令通过 CLI 创建 Web API 微服务:
dotnet new webapi -n ProductService
这里,ProductService
就是一个微服务,它可以提供产品相关的业务逻辑。
1.2 定义模型和控制器
为你的微服务定义模型类和控制器。
模型类 Product.cs
:
public class Product { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } }
控制器类 ProductsController.cs
:
[ApiController] [Route("api/[controller]")] public class ProductsController : ControllerBase { private static List<Product> products = new List<Product> { new Product { Id = 1, Name = "Laptop", Price = 1200 }, new Product { Id = 2, Name = "Phone", Price = 800 } }; [HttpGet] public ActionResult<IEnumerable<Product>> Get() { return Ok(products); } [HttpGet("{id}")] public ActionResult<Product> Get(int id) { var product = products.FirstOrDefault(p => p.Id == id); if (product == null) return NotFound(); return Ok(product); } [HttpPost] public IActionResult Post([FromBody] Product product) { products.Add(product); return CreatedAtAction(nameof(Get), new { id = product.Id }, product); } }
这个示例定义了一个简单的产品管理微服务,提供 RESTful API,可以获取、添加产品信息。
1.3 跨服务通信
在微服务架构中,各服务需要通信。ASP.NET Core 微服务之间可以通过以下方式通信:
-
HTTP:通过
HttpClient
发起 HTTP 请求,服务之间使用 RESTful API 进行通信。 -
gRPC:通过 gRPC 进行高性能的 RPC 调用。
-
消息队列:使用 RabbitMQ、Kafka 等消息中间件进行异步通信。
使用 HttpClient
进行跨服务通信:
public class ProductServiceClient { private readonly HttpClient _httpClient; public ProductServiceClient(HttpClient httpClient) { _httpClient = httpClient; } public async Task<Product> GetProductAsync(int id) { var response = await _httpClient.GetAsync($"http://productservice/api/products/{id}"); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsAsync<Product>(); } }
1.4 服务发现
微服务在大规模部署时可能会动态扩展或重启,导致 IP 地址变化。服务发现可以通过 Consul、Eureka 等工具来管理服务实例。
使用 Consul
进行服务发现的一个示例:
-
启动
Consul
服务。 -
每个微服务启动时在
Consul
中注册自己。 -
通过
Consul
查找其他微服务的地址。
在 ASP.NET Core 中,可以通过 HttpClient
工厂与 Consul 集成,动态发现服务。
1.5 容错和重试机制
微服务之间通信时,网络不稳定或服务不可用可能导致请求失败。为了提升稳定性,你可以使用容错和重试机制。
-
Polly 是一个容错和重试库,ASP.NET Core 提供了与 Polly 的集成,可以轻松添加重试、断路器等机制。
使用 Polly 添加重试策略:
services.AddHttpClient<ProductServiceClient>() .AddTransientHttpErrorPolicy(policy => policy.RetryAsync(3)); // 3 次重试
1.6 容器化微服务
为了更好地部署和管理微服务,通常将微服务容器化。
-
创建 Dockerfile: 在项目根目录下创建一个
Dockerfile
,用于将微服务容器化:
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base WORKDIR /app EXPOSE 80 FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build WORKDIR /src COPY . . RUN dotnet restore RUN dotnet build -c Release -o /app/build FROM build AS publish RUN dotnet publish -c Release -o /app/publish FROM base AS final WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "ProductService.dll"]
-
构建和运行 Docker 镜像:
docker build -t productservice . docker run -d -p 8080:80 productservice
1.7 使用 Kubernetes 管理微服务
Kubernetes 是一个流行的容器编排工具,可以帮助管理容器化的微服务。
(1)创建 Kubernetes 部署文件 deployment.yaml
:
apiVersion: apps/v1 kind: Deployment metadata: name: productservice spec: replicas: 3 selector: matchLabels: app: productservice template: metadata: labels: app: productservice spec: containers: - name: productservice image: productservice:latest ports: - containerPort: 80
(2)部署到 Kubernetes:
kubectl apply -f deployment.yaml
通过 Kubernetes,可以轻松实现自动扩展、负载均衡和容错。
6.将现有的 ASP.NET Core项目进行微服务分解
要将现有的 ASP.NET Core项目分解为多个独立的微服务,首先需要了解该项目中的功能模块和业务逻辑。每个模块或服务都应单独处理某个特定的职责,并能独立开发、部署和扩展。你可以考虑以下几个方面来划分微服务:
1. 功能模块划分
根据项目的业务逻辑,识别出可以单独处理的功能模块。常见的模块包括:
-
用户管理服务:负责处理用户的注册、登录、权限管理等操作。
-
通知服务:处理系统中的通知(如校车推送、公告等)。
-
学生信息管理服务:负责处理与学生相关的数据(如学生信息、成绩、课程等)。
-
家长服务:管理家长相关的信息和操作,如与子女关联、查看信息等。
-
微信通知服务:处理微信的消息和模板通知功能。
2. 数据库和数据访问分离
每个微服务应拥有自己的数据库或数据存储,这样可以确保服务之间的独立性。可以将与学生、通知、家长等不同业务领域相关的数据库分离。例如:
-
用户数据库:存储用户的登录信息、角色、权限等。
-
学生数据库:存储学生个人信息、学业记录等。
-
通知数据库:存储系统通知信息,如公告、推送记录。
3. API Gateway
使用 API 网关作为入口点,协调多个微服务的请求。API 网关的功能包括:
-
路由外部请求到相应的微服务。
-
负载均衡、限流等操作。
-
在复杂应用中,可以集成认证、缓存等功能。
4. 典型服务划分
根据你的项目架构,可以考虑以下服务划分:
-
用户认证服务(Authentication Service): 处理所有与用户认证相关的操作,包括登录、注册、授权。此服务独立于其他功能模块,可以通过 OAuth 或 JWT 进行用户身份验证。
-
校车推送服务(Bus Notification Service): 专门处理校车的通知和推送功能,独立的推送逻辑可以让服务灵活扩展或与外部服务(如微信通知)集成。
-
消息服务(Message Service): 处理系统的消息通知,包含微信消息、校内公告等。你当前项目中涉及到大量通知和消息逻辑,完全可以拆分为一个独立的服务。
-
学生信息管理服务(Student Info Service): 处理学生的基本信息、学籍管理和课程安排等。任何需要与学生相关的数据操作都会通过该服务来执行。
5. 服务通信方式
-
同步通信:可以使用 HTTP 或 gRPC 协议,确保服务之间快速通信。适合需要及时响应的场景。
-
异步通信:对于不需要即时反馈的操作,可以使用消息队列(如 RabbitMQ 或 Kafka)来实现异步通信。适合任务队列、通知推送等操作。
6. 容错和重试
为了确保系统的稳定性,在微服务间调用时可以使用像 Polly 这样的库来实现重试和容错策略,以应对网络不稳定或服务暂时不可用的情况。
7. 示例划分
-
用户服务:负责用户登录、身份验证、权限管理。
-
通知服务:处理各种通知,如微信推送、短信等。
-
学生管理服务:管理学生的基本信息和学籍相关功能。
-
家长服务:专注于家长与学生的关系维护,查看信息等功能。
-
日志服务:处理系统日志记录和分析。
7.微服务之间的通信
(1)使用 HTTP 进行微服务通信
假设有一个用户服务和一个学生信息管理服务。用户服务需要验证用户身份后才能获取学生信息。
-
用户服务:
-
提供一个登录接口:
POST /api/auth/login
-
登录成功后返回一个 JWT 令牌。
-
-
学生信息管理服务:
-
提供一个获取学生信息的接口:
GET /api/students/{studentId}
-
用户服务在调用学生服务时,会在请求头中附加 JWT 令牌进行身份验证。
-
(2)使用消息队列(MQ)或 Kafka 进行微服务通信
在使用消息队列或 Kafka 时,服务之间的通信通常是异步的,适合处理不需要立即响应的场景。
-
示例场景:
-
当用户注册后,用户服务会向消息队列发送一个注册成功的消息,通知其他服务(如通知服务)。
-
-
用户服务:
-
发布消息:
// 使用 RabbitMQ 作为示例 var message = new { UserId = user.Id, Message = "User registered." }; var body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message)); channel.BasicPublish(exchange: "", routingKey: "user-registered", body: body);
-
-
通知服务:
-
监听消息:
// 从 RabbitMQ 消费者获取消息 var consumer = new EventingBasicConsumer(channel); consumer.Received += (model, ea) => { var body = ea.Body.ToArray(); var message = JsonConvert.DeserializeObject<Message>(Encoding.UTF8.GetString(body)); // 处理通知逻辑 }; channel.BasicConsume(queue: "user-registered", autoAck: true, consumer: consumer);
-
(3)总结
-
HTTP:适合需要实时交互的场景,通过 RESTful API 或 gRPC 进行服务调用。
-
消息队列/Kafka:适合异步处理的场景,服务通过发布/订阅模型进行通信,解耦服务之间的依赖。
8.Entity Framework Core(EF Core)
(1)定义
Entity Framework Core(EF Core)是 Microsoft 开发的一个轻量级、跨平台的对象关系映射(ORM)框架,旨在简化 .NET 应用程序与数据库之间的交互。EF Core 允许开发者使用 .NET 对象操作数据库,而无需直接处理 SQL 语句。
主要特点包括:
-
跨平台支持:可以在 Windows、Linux 和 macOS 上使用。
-
灵活的数据库支持:支持多种数据库,包括 SQL Server、SQLite、PostgreSQL 和 MySQL 等。
-
LINQ 查询:使用 LINQ(语言集成查询)来构建数据库查询,提供更强的类型安全和可读性。
-
代码优先和数据库优先:支持通过代码定义模型(代码优先)或从现有数据库生成模型(数据库优先)。
-
迁移支持:提供数据库迁移功能,方便管理数据库架构的演变。
EF Core 使得开发者能够更高效地进行数据访问和管理,提升了开发效率和代码可维护性。
(2)CRUD代码实操
1. 创建模型
创建一个简单的 Student
类,作为数据库模型。
public class Student { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } }
2. 创建数据库上下文
创建一个 SchoolContext
类,继承自 DbContext
。
using Microsoft.EntityFrameworkCore; public class SchoolContext : DbContext { public DbSet<Student> Students { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("YourConnectionStringHere"); } }
3. CRUD 操作示例
以下是一个简单的示例,展示如何进行基本的 CRUD 操作:
using (var context = new SchoolContext()) { // 创建 var student = new Student { Name = "Alice", Age = 21 }; context.Students.Add(student); context.SaveChanges(); // 读取 var students = context.Students.ToList(); // 更新 var studentToUpdate = context.Students.First(); studentToUpdate.Age = 22; context.SaveChanges(); // 删除 var studentToDelete = context.Students.First(); context.Students.Remove(studentToDelete); context.SaveChanges(); }
9. 控制反转(IoC)与依赖注入(DI)
(1)控制反转(IoC) 是一种设计原则,指的是将对象的控制权反转给外部容器,而不是由对象自身管理其依赖。这样可以降低组件之间的耦合度,提高灵活性和可维护性。
(2)依赖注入(DI) 是实现 IoC 的一种具体方式。通过 DI,可以将所需的依赖项以参数的形式注入到类中,而不是在类内部创建这些依赖项。
(3)不使用 DI 的代码示例:
public class PathPlanner { private readonly Logger _logger; public PathPlanner() { _logger = new Logger(); // 直接创建依赖 } public void PlanPath() { _logger.Log("Planning path..."); // 其他逻辑 } }
使用 DI 的代码示例:
public class PathPlanner { private readonly ILogger _logger; // 通过构造函数注入依赖 public PathPlanner(ILogger logger) { _logger = logger; } public void PlanPath() { _logger.Log("Planning path..."); // 其他逻辑 } }
在使用 DI 时,可以使用依赖注入容器(如 Microsoft.Extensions.DependencyInjection)来管理这些依赖项。
10. Dapper
Dapper 是一个轻量级的对象关系映射(ORM)库,用于在 .NET 应用程序中简化数据库操作。它通过简单的 SQL 查询实现快速的数据访问,同时保持较高的性能。
示例
假设要在校车线路规划中从数据库获取一些线路数据,可以使用 Dapper 这样做:
using (var connection = new SqlConnection("YourConnectionString")) { connection.Open(); var sql = "SELECT * FROM Paths WHERE Id = @Id"; var path = connection.QuerySingle<Path>(sql, new { Id = pathId }); }
Dapper 使得从数据库中查询数据变得简单而高效,尤其适合对性能有较高要求的场景。
11. NLog
NLog 是一个用于 .NET 应用程序的日志框架,支持多种日志目标(如文件、数据库、控制台等)和灵活的配置。它允许记录应用程序的运行时信息,以便于调试和监控。
示例
在你的车辆路径规划模型中,你可以使用 NLog 来记录日志:
private static readonly Logger logger = LogManager.GetCurrentClassLogger(); public void PlanPath() { logger.Info("Starting path planning..."); // 其他逻辑 logger.Info("Path planning completed."); }
你需要在项目中配置 NLog,以指定日志输出的目标和格式。
更多推荐
所有评论(0)