.Net测试卷题二

1、NetCore中,介绍一下**ConfigureServices** 和 **Configure**职责有何不同

ConfigureServicesConfigure 是在ASP.NET Core应用程序的启动过程中用于配置服务和应用程序管道的两个重要方法。

  1. ConfigureServices:
    • ConfigureServices 方法用于配置应用程序的服务容器,即依赖注入容器。在这个方法中,你可以注册应用程序所需的各种服务,例如数据库上下文、存储库、日志记录器等。
    • 这个方法在应用程序启动时执行一次,它是在依赖注入容器创建之后、应用程序处理请求之前调用的。
    • ConfigureServices 方法的主要职责是设置应用程序所需的依赖注入服务,以便它们可以在应用程序的其他部分中使用。
  2. Configure:
    • Configure 方法用于配置应用程序的HTTP请求处理管道,它定义了请求的处理顺序和中间件的使用。
    • 在这个方法中,你可以添加中间件(Middleware)到管道中,以实现不同的功能,例如身份验证、路由、异常处理等。
    • Configure 方法在每次收到HTTP请求时都会被调用,用于构建请求处理管道,每个请求都会经过该管道以执行必要的处理和操作。

总结:

  • ConfigureServices 方法用于配置应用程序的依赖注入容器,注册所需的服务。
  • Configure 方法用于配置应用程序的HTTP请求处理管道,定义请求的处理顺序和中间件的使用。

请注意,这些方法通常在 Startup.cs 文件中被重写,以实现自定义的应用程序配置和行为。

2、NetCore中,如何配置多环境(例开发环境,测试环境,生产环境的不同链接字符串)

在ASP.NET Core中,你可以使用配置系统来管理不同环境下的配置信息,包括数据库连接字符串等。以下是配置多环境的一般步骤:

  1. 创建不同环境的配置文件:
    在你的项目根目录下,创建不同环境的配置文件,例如 appsettings.Development.json(开发环境)、appsettings.Staging.json(测试环境)、appsettings.Production.json(生产环境)等。每个文件中可以包含相应环境下的配置信息,例如数据库连接字符串。

  2. 设置环境变量:
    在你的应用程序中设置环境变量来指定当前运行的环境。在开发阶段,你可以通过 Visual Studio 或其他方式设置环境变量为 “Development”。在实际部署到测试和生产环境时,确保设置正确的环境变量值。

  3. 配置文件加载:
    Startup.cs 文件的 ConfigureServices 方法中,使用 Configuration 对象来加载不同环境的配置文件。ASP.NET Core会自动根据当前环境加载相应的配置文件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    csharpCopy code
    public void ConfigureServices(IServiceCollection services)
    {
    // 加载不同环境的配置文件
    var env = HostingEnvironment.EnvironmentName; // 获取当前环境名称
    var configBuilder = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile($"appsettings.{env}.json", optional: false, reloadOnChange: true)
    .AddEnvironmentVariables();

    Configuration = configBuilder.Build();

    // 注册配置对象
    services.AddSingleton(Configuration);

    // ...其他服务配置...
    }
  4. 在应用程序中使用配置:
    在需要使用配置的地方,可以通过依赖注入来获取配置对象,并获取相应的值,例如数据库连接字符串。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    csharpCopy code
    public class MyService
    {
    private readonly IConfiguration _configuration;

    public MyService(IConfiguration configuration)
    {
    _configuration = configuration;
    }

    public void DoSomething()
    {
    var connectionString = _configuration.GetConnectionString("DefaultConnection");
    // 使用连接字符串进行操作...
    }
    }

通过这种方式,你可以在不同环境下使用不同的配置信息,例如数据库连接字符串,而无需修改应用程序的代码。这有助于简化配置管理和部署过程。

3、NetCore中,描述一下依赖注入后的服务生命周期

在ASP.NET Core中,依赖注入(DI)是一种设计模式,用于将组件的依赖关系从它们的实现中解耦,从而提高代码的可维护性和可测试性。ASP.NET Core通过内置的依赖注入容器来管理和解析服务的生命周期。以下是ASP.NET Core中支持的三种主要服务生命周期:

  1. 瞬时(Transient)生命周期:
    • 对于瞬时生命周期的服务,每次调用**IServiceProvider.GetService<T>**都会创建一个新的实例。
    • 这种生命周期适用于轻量级、无状态的服务,每次调用需要获得一个全新的实例。
    • 在依赖注入容器中,可以使用**services.AddTransient<TService, TImplementation>()**方法注册瞬时生命周期的服务。
  2. 作用域(Scoped)生命周期:
    • 对于作用域生命周期的服务,容器会为每个HTTP请求创建一个单独的实例,并在整个请求周期内重用这个实例。
    • 这种生命周期适用于需要在一个HTTP请求范围内共享状态的服务,例如数据库上下文。
    • 在依赖注入容器中,可以使用**services.AddScoped<TService, TImplementation>()**方法注册作用域生命周期的服务。
  3. 单例(Singleton)生命周期:
    • 对于单例生命周期的服务,容器会创建一个单一的实例,并在整个应用程序的生命周期内重用这个实例。
    • 这种生命周期适用于全局唯一的、可共享的状态,例如配置信息、日志记录器等。
    • 在依赖注入容器中,可以使用**services.AddSingleton<TService, TImplementation>()**方法注册单例生命周期的服务。

ASP.NET Core的依赖注入容器负责创建、管理和释放这些不同生命周期的服务,确保按需创建、重用和销毁实例,以满足应用程序的需求。你可以根据每个服务的特性和需求来选择适当的生命周期。

4、NetCore中,什么是中间件?如何造成管道短路?什么情况下需要造成管道短路?

🎇 中间件(Middleware)是一种用于处理HTTP请求和响应的组件。中间件在应用程序的请求处理管道中起到中介的作用,它可以在请求到达最终目标之前或响应发送到客户端之前执行各种操作。中间件可以执行日志记录、身份验证、授权、异常处理等任务,以及修改请求和响应的内容。

🏘️ 每个中间件都可以执行一些操作,然后将请求传递给下一个中间件,或者中间件可以决定中断管道的流程,从而造成管道短路。管道短路意味着在某个中间件中处理了请求并生成了响应,不再将请求传递给下一个中间件。

造成管道短路的情况可能包括:

  1. 身份验证和授权失败: 如果中间件负责身份验证或授权,当请求的身份验证失败或授权不通过时,可以生成一个适当的响应并中断管道。
  2. 异常处理: 如果在中间件中捕获到异常,并且你希望返回一个错误响应而不是将请求继续传递给后续中间件,你可以造成管道短路。
  3. 请求预处理: 有时,某些中间件可能会在处理请求之前执行某些预处理操作,如果预处理操作确定请求无效或不需要进一步处理,可以造成管道短路。
  4. 静态文件处理: 当中间件处理静态文件请求时,如果找到匹配的静态文件并生成了响应,可以造成管道短路,避免进一步处理。

5、如何保证接口安全性?

  1. 身份验证(Authentication)和授权(Authorization):
    • 使用适当的身份验证机制,如JWT(JSON Web Token)或OAuth,来验证用户的身份。
    • 基于用户的身份和角色,进行授权,确保只有具有足够权限的用户可以访问特定的接口和资源。
  2. HTTPS加密:
    • 使用HTTPS协议来加密数据传输,确保数据在传输过程中不会被篡改或窃取。
  3. 防止跨站请求伪造(CSRF):
    • 使用CSRF令牌来防止恶意站点利用用户的身份执行未经授权的操作。
  4. 输入验证和数据校验:
    • 对于从用户输入获得的数据,进行有效性验证和数据校验,以防止恶意数据或不良输入引发安全问题。
  5. 防止SQL注入:
    • 使用参数化查询或ORM(对象关系映射)工具来构建数据库查询,以防止SQL注入攻击。
  6. 日志记录和监控:
    • 在接口中实现详细的日志记录,以便在出现异常或安全问题时进行追踪和分析。
    • 使用监控工具来检测和响应潜在的安全事件。
  7. 安全头部设置:
    • 在HTTP响应中设置适当的安全头部,如CSP(内容安全策略)、X-XSS-Protection(跨站脚本保护)等,以增加浏览器端的安全性。
  8. 输入过滤和输出编码:
    • 对于从用户获取的输入数据,进行输入过滤,以过滤掉恶意或不合法的内容。
    • 在将数据返回给用户时,进行输出编码,以防止跨站脚本攻击(XSS)。

6、如何保证接口幂等性?

  1. HTTP方法选择:
    • 使用合适的HTTP方法来表示操作的性质。GET请求应该是安全且幂等的,而不应该用于具有副作用的操作。推荐使用POST、PUT或DELETE方法来执行有状态的、可能引起副作用的操作。
  2. 唯一标识符和标记:
    • 在每次请求中使用唯一的标识符或标记来区分不同的请求。可以使用UUID、请求ID等唯一值来区分请求,确保相同的请求不会重复执行。
  3. 使用幂等性操作:
    • 设计接口操作以支持幂等性。例如,重复执行同一个请求应该产生相同的结果,不会产生重复的资源或状态变化。
  4. 幂等性检查:
    • 在处理请求之前,检查请求是否已经被处理过。可以在数据库中存储请求的唯一标识符或哈希值,并在处理请求时进行检查,避免重复操作。
  5. 乐观并发控制:
    • 使用乐观并发控制来处理并发请求。在更新操作中,使用版本号或时间戳来确保只有最新版本的数据被更新。
  6. 幂等性令牌:
    • 为每个请求生成并返回一个幂等性令牌,在下次请求中将该令牌作为参数或头部发送。服务器验证令牌,确保重复请求不会重复执行。
  7. 不会引起状态变化的查询操作:
    • 对于读取数据的查询操作,如GET请求,应该是幂等的,因为它们不会引起系统状态的变化。

7、使用过哪些0rm框架,简要介绍下异同及优缺点

Entity Framework(EF):

  • 异同:
    • EF是由Microsoft开发的,集成度高,与.NET生态系统深度整合。
    • 支持多种开发模式,如Code First、Database First和Model First。
    • 提供了强大的LINQ查询功能,能够将数据库查询转化为C#代码。
    • 提供了多种数据库提供程序,如SQL Server、MySQL、SQLite等。
  • 优点:
    • 良好的开发体验,简化了数据库映射和查询。
    • 集成度高,与Visual Studio无缝集成。
    • 丰富的文档和社区支持。
  • 缺点:
    • 性能相对较慢,特别是在复杂查询或大规模数据处理中。
    • 部分高级特性需要更多配置和调整。

SqlSugar:

  • 异同:
    • SqlSugar是一个轻量级的ORM框架,专注于高性能。
    • 提供了丰富的特性,支持Lambda表达式和原生SQL。
    • 可以工作在多个数据库后端,如SQL Server、MySQL、Oracle等。
    • 功能相对精简,主要关注数据库访问和操作。
  • 优点:
    • 高性能,与原生SQL查询接近,适合需要高性能的应用。
    • 易于学习和使用,不需要复杂的映射配置。
    • 支持批量操作和存储过程。
  • 缺点:
    • 功能相对较少,不如EF提供的功能丰富。
    • 不太适合复杂的领域模型映射。

8、分布式事务中,如何保证事务的最终一致性。可简要介绍下思路或者用过的相关框架

🤑在分布式系统中,保证事务的最终一致性是一个复杂而重要的问题。

🤑最终一致性指的是尽管分布式系统中的数据可能在某一时刻不一致,但在一段时间后,系统会达到一致的状态。

以下是一些常见的思路和相关框架来实现分布式事务的最终一致性:

  1. 两阶段提交(Two-Phase Commit,2PC):
    • 2PC是一种协调分布式事务的协议,它涉及一个协调者和多个参与者。在这个协议中,协调者询问所有参与者是否可以提交事务,然后协调者根据收到的参与者回复来决定是否执行提交操作。
    • 优点:简单易懂,可以保证事务的最终一致性。
    • 缺点:性能较差,可能存在阻塞问题,参与者故障会导致协议阻塞。
  2. 补偿事务(Compensating Transaction):
    • 补偿事务是一种通过执行一系列补偿操作来回滚或纠正事务的策略。当某个分布式事务失败时,可以通过执行一些特定的操作来修复系统状态,使其恢复到一致的状态。
    • 优点:灵活性高,能够应对各种复杂情况,如网络故障、部分节点故障等。
    • 缺点:实现和维护成本较高,需要额外的编码和逻辑。

分布式框架:

  • 阿里的
  • 华为的

9、索引的优缺点。索引的类型。事务的级别和默认级别

索引的优缺点:

优点:

1. **提高检索性能:** 索引可以加速数据库查询操作,降低查询的时间复杂度。
2. **加速排序和分组:** 对于包含索引的列进行排序或分组操作时,索引可以显著提高性能。
3. **加速连接操作:** 在表之间进行连接操作时,索引可以减少连接的复杂度,提高查询效率。
4. **唯一性约束:** 唯一索引可以确保某一列的值在表中唯一,保证数据的完整性。
5. **加速外键关联:** 对于外键关联的列,创建索引可以加速关联操作的效率。

缺点:

1. **占用存储空间:** 索引需要占用额外的存储空间,特别是对于大型表,可能会显著增加存储需求。
2. **降低写操作性能:** 更新、插入和删除操作会涉及索引的维护,可能导致写操作性能下降。
3. **增加维护成本:** 随着数据的变化,索引需要不断地维护,可能导致数据库性能下降。
4. **可能导致查询性能下降:** 当索引选择不当或过多时,查询优化器可能选择错误的索引,导致查询性能下降。

索引的类型:

1. **唯一索引(Unique Index):** 确保索引列的值在表中唯一。
2. **主键索引(Primary Key Index):** 一种特殊的唯一索引,用于标识表中的唯一记录。
3. **聚集索引(Clustered Index):** 确定表的物理存储顺序,每个表只能有一个聚集索引。
4. **非聚集索引(Non-clustered Index):** 不影响表的物理存储顺序,可以有多个非聚集索引。
5. **复合索引(Composite Index):** 包含多个列的索引,用于优化多列条件的查询。
6. **全文索引(Full-Text Index):** 用于全文搜索,支持关键词和文本搜索

事务的级别和默认级别:

事务的级别是指事务在数据库中的隔离程度。常见的事务级别包括:

1. **Read Uncommitted(读未提交):** 最低级别,一个事务可以读取另一个未提交事务的数据。
2. **Read Committed(读已提交):** 默认级别,一个事务只能读取已提交事务的数据。
3. **Repeatable Read(可重复读):** 保证在同一事务内多次读取同一数据时,数据保持一致,但允许幻读问题。

10、单表数据量过大,造成插入及读取性能问题,你会如何优化?

  1. 分区(Partitioning): 将大表分割成多个较小的子表,每个子表存储一定范围的数据。可以根据时间、地理位置等进行分区,减轻单表数据量压力。
  2. 索引优化: 确保表上的索引使用合理,避免过多或不必要的索引。优化索引可以提高查询性能。
  3. 缓存: 使用缓存来存储热门数据,减少频繁的数据库查询。缓存可以是内存数据库(如Redis)或分布式缓存。
  4. 归档: 将历史数据归档到独立的表中,保留最新和最活跃的数据在主表中。这可以减少主表的数据量,提高查询性能。
  5. 分库分表(Sharding): 将数据拆分到多个数据库实例或表中,每个数据库实例或表负责一部分数据。这可以提高并发性和扩展性。
  6. 批量操作: 在插入和更新操作中使用批量操作,而不是逐条操作。批量操作可以减少事务和日志开销。
  7. 定时清理: 定期清理不再需要的数据,如过期数据或历史数据。这可以保持表的数据量在可管理的范围内。
  8. 使用分布式数据库: 考虑使用分布式数据库系统,可以通过分布式架构来分散数据负载。
  9. 垂直拆分: 将表按功能或业务逻辑进行拆分,每个表只包含相关的字段和数据,从而降低单表数据量。
  10. 数据压缩: 对表中的数据进行压缩,减小存储空间,提高数据的读取性能。

11、说下自己对Restful框架的了解(Http动作,响应状态码,路由等)

RESTful框架是一种用于构建Web服务的架构风格,它强调资源的概念和基于HTTP协议的设计原则。以下是我对RESTful框架的一些基本了解:

  1. HTTP动作(HTTP Methods):
    RESTful框架通过HTTP方法来表示对资源的操作。常用的HTTP动作包括:
    • GET: 用于获取资源的信息。
    • POST: 用于创建新资源。
    • PUT: 用于更新或替换资源。
    • DELETE: 用于删除资源。
    • PATCH: 用于部分更新资源。
  2. 响应状态码(HTTP Status Codes):
    RESTful框架使用HTTP状态码来表示请求的处理结果。一些常见的HTTP状态码及其含义包括:
    • 200 OK: 请求成功。
    • 201 Created: 资源创建成功。
    • 204 No Content: 没有内容返回。
    • 400 Bad Request: 请求格式错误或参数错误。
    • 401 Unauthorized: 没有认证或认证失败。
    • 403 Forbidden: 没有权限访问资源。
    • 404 Not Found: 资源不存在。
    • 405 Method Not Allowed: 不允许使用该HTTP方法。
    • 500 Internal Server Error: 服务器内部错误。
  3. 路由(Routing):
    在RESTful框架中,URL用于表示资源,路由机制将URL映射到相应的资源和操作。通常,URL的结构反映了资源的层次结构。例如,**/users表示用户资源,/users/{id}**表示特定用户的详细信息。

12.是否了解Docker,简单介绍下。写一下列出本机所有镜像,列出本机所有容器的命令

  • docker images
  • docker ps -a

13、编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符串数组char[]的形式给出不要给另外的数据分配额外的空间,必须原地修改输入数组,使用0(1)的额外空间解决这一问题

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
public class Solution {
public void ReverseString(char[] s) {
int left = 0;
int right = s.Length - 1;

while (left < right) {
// 交换左右指针指向的字符
char temp = s[left];
s[left] = s[right];
s[right] = temp;

// 移动指针向中间移动
left++;
right--;
}
}
}

class Program {
static void Main(string[] args) {
char[] inputStr = { 'h', 'e', 'l', 'l', 'o' };
Solution solution = new Solution();
solution.ReverseString(inputStr);

Console.WriteLine(inputStr); // 输出 "olleh"
}
}