当前位置: 首页 > news >正文

【ASP.NET CORE】 4. 集成配置系统、分层架构

本系列专栏基于杨中科老师的《ASP.NET Core技术内幕与项目实战》,本人记录梳理的学习笔记,有部分的增补和省略。更全面系统的讲解,请看杨老师的视频课:【.NET教程,.Net Core视频教程,杨中科主讲】

一、配置系统使用

ASP.NET Core 配置系统采用提供者模式,支持多源配置、热更新、环境隔离,是项目开发的核心基础,以下是完整使用指南。

1. 默认配置提供者(加载优先级:后加载覆盖先加载)

ASP.NETCore 主机默认按固定顺序加载配置源,后续配置会覆盖同名键值,生产环境需严格遵循优先级规范:

  1. 加载已注入的IConfiguration根配置对象;
  2. 加载项目根目录的appsettings.json(基础公共配置);
  3. 加载环境差异化配置appsettings.{Environment}.json(环境专属配置);
  4. 开发环境专属:加载用户机密配置(secrets.json,本地敏感信息);
  5. 加载系统环境变量(容器 / 服务器级配置);
  6. 加载命令行参数(临时启动配置,优先级最高)。

2. 运行环境模式(环境隔离核心)

ASP.NETCore 通过环境变量区分运行环境,实现开发 / 测试 / 生产配置完全隔离,避免配置混淆引发线上问题。

  • 环境变量名:固定为ASPNETCORE_ENVIRONMENT
  • 官方推荐值:
    • Development:开发环境(本地调试,启用 Swagger、用户机密)
    • Staging:测试 / 预发环境(模拟生产验证)
    • Production:生产环境(禁用调试、开启日志压缩)
  • 环境判断方法:
    • 获取环境名称:app.Environment.EnvironmentName
    • 快速判断:app.Environment.IsDevelopment()/IsStaging()/IsProduction()
示例

开发环境仅启用 Swagger

var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); // 仅开发环境加载Swagger,生产环境自动禁用 if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.Run();

3. 用户机密

核心作用:存储数据库连接串、密钥、Token 等不能提交到 Git / 服务器的本地机密信息,仅开发环境使用,绝对不用于生产环境

使用
  1. 右键ASP.NETCore 项目 → 选择【管理用户机密】,自动生成secrets.json
  2. 机密文件物理路径:
    • Windows:C:\Users\用户名\AppData\Roaming\Microsoft\UserSecrets\{UserSecretsId}\secrets.json
    • Mac/Linux:~/.microsoft/usersecrets/{UserSecretsId}/secrets.json
  3. 项目关联:通过项目文件.csproj中的<UserSecretsId>唯一标识绑定,无需手动配置路径。
secrets.json 示例

(存储数据库连接串)

{ "ConnectionStrings": { "Default": "Data Source=.;Initial Catalog=demo1;Integrated Security=SSPI;TrustServerCertificate=true" } }

4. 配置实战

(数据库配置 + Redis 集成)

生产环境推荐:核心配置存入专用数据库,连接串存入用户机密,实现配置中心化管理。依赖:Zack.AnyDBConfigProvider(轻量级数据库配置提供者)

步骤 1:注册数据库配置源
var builder = WebApplication.CreateBuilder(args); // 1. 从用户机密读取配置数据库连接串 string configConnStr = builder.Configuration.GetConnectionString("Default"); // 2. 注册数据库配置提供者(加载Redis、Smtp等核心配置) builder.Configuration.AddDBConfig(opts => { opts.DbType = DbType.SqlServer; // 数据库类型 opts.ConnectionString = configConnStr; // 配置库连接串 }); // 3. 读取配置并绑定为强类型对象(推荐:类型安全,避免魔法字符串) var redisConfig = builder.Configuration.GetSection("Redis").Get<RedisConfig>(); var smtpConfig = builder.Configuration.GetSection("Smtp").Get<SmtpConfig>(); // 4. 注册Redis服务(程序启动时初始化,注入DI容器) builder.Services.AddStackExchangeRedisCache(options => { options.Configuration = redisConfig.ConnectionString; options.InstanceName = "DemoRedis"; }); // 注册配置对象到DI,方便控制器使用 builder.Services.AddSingleton(redisConfig); builder.Services.AddSingleton(smtpConfig);
步骤 2:强类型配置实体(推荐)
// Redis配置 public class RedisConfig { public string ConnectionString { get; set; } public int DefaultDB { get; set; } } // Smtp邮件配置 public class SmtpConfig { public string Server { get; set; } public int Port { get; set; } public string UserName { get; set; } public string Password { get; set; } }
步骤 3:控制器中读取配置
[ApiController] [Route("api/[controller]")] public class ConfigController : ControllerBase { private readonly SmtpConfig _smtpConfig; // 依赖注入配置对象 public ConfigController(SmtpConfig smtpConfig) { _smtpConfig = smtpConfig; } [HttpGet("smtp")] public IActionResult GetSmtpConfig() { // 返回Smtp配置到前端(生产环境隐藏敏感字段) return Ok(new { Server = _smtpConfig.Server, Port = _smtpConfig.Port }); } }

二、项目分层

大型项目禁止所有代码写在 Web 项目中,推荐领域驱动分层核心思想:数据层独立、Web 层仅负责配置和入口

标准分层结构

  1. XXX.EFCore:数据访问层(实体类、EF 上下文、配置映射)
  2. XXX.WebApi:Web 入口层(控制器、配置、依赖注入)
  3. (扩展)XXX.Application:业务逻辑层;XXX.Domain:领域模型层

实战

Books 项目分层实现

1. 创建数据访问类库:BooksEFCore
  • 新建【.NET 类库项目】,命名BooksEFCore
  • 安装 NuGet 包:
    Install-Package Microsoft.EntityFrameworkCore.Relational Install-Package Microsoft.EntityFrameworkCore.Tools Install-Package Microsoft.EntityFrameworkCore.SqlServer
2. 编写实体类 + 配置类
// 实体类:Book.cs public class Book { public long Id { get; set; } public string Title { get; set; } public string AuthorName { get; set; } public decimal Price { get; set; } public DateTime PubDate { get; set; } } // 配置类:FluentAPI配置(推荐:分离实体和配置) public class BookConfig : IEntityTypeConfiguration<Book> { public void Configure(EntityTypeBuilder<Book> builder) { builder.ToTable("T_Books"); // 表名 builder.Property(b => b.Title).IsRequired().HasMaxLength(200); builder.Property(b => b.AuthorName).IsRequired().HasMaxLength(50); } }
3. 编写 DbContext

通过构造函数注入DbContextOptions不重写 OnConfiguring,实现数据库配置与上下文解耦。

public class MyDbContext : DbContext { // 构造函数注入配置(Web层统一配置) public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { } public DbSet<Book> Books => Set<Book>(); // 加载配置 protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 批量加载当前程序集的所有配置类 modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly); } }
// 不要在上下文硬编码连接串!无法切换数据库、无法测试 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("连接串"); }
4. Web 层配置
  1. 添加对BooksEFCore项目的引用
  2. 注册 DbContext 到依赖注入:
var builder = WebApplication.CreateBuilder(args); // 从配置系统读取连接串 string connStr = builder.Configuration.GetConnectionString("Default"); // 注册DbContext builder.Services.AddDbContext<MyDbContext>(opt => { opt.UseSqlServer(connStr); // 可轻松切换为UseMySQL/UsePostgre });
5. 控制器中使用 DbContext
[ApiController] [Route("api/[controller]")] public class BookController : ControllerBase { private readonly MyDbContext _dbContext; // 依赖注入上下文 public BookController(MyDbContext dbContext) { _dbContext = dbContext; } [HttpGet] public async Task<IActionResult> GetBooks() { var books = await _dbContext.Books.ToListAsync(); return Ok(books); } }
6. 多项目迁移避坑

问题:迁移脚本生成时,EF 无法直接读取 Web 层配置,会报错。

解决方案:在BooksEFCore中创建设计时上下文工厂(IDesignTimeDbContextFactory),仅用于生成迁移脚本。

/// <summary> /// EF迁移设计时工厂(仅开发环境生成迁移使用) /// </summary> internal class MyDbContextDesignFactory : IDesignTimeDbContextFactory<MyDbContext> { public MyDbContext CreateDbContext(string[] args) { var builder = new DbContextOptionsBuilder<MyDbContext>(); // 开发环境数据库连接串(可读取环境变量) string connStr = Environment.GetEnvironmentVariable("DefaultConnection") ?? "Data Source=.;Initial Catalog=demo666;Integrated Security=SSPI;TrustServerCertificate=true"; builder.UseSqlServer(connStr); return new MyDbContext(builder.Options); } }
7. 生成迁移脚本
  1. BooksEFCore设置为启动项目
  2. 打开【程序包管理器控制台】,默认项目选择BooksEFCore
  3. 执行命令:
    Add-Migration InitBook // 生成迁移文件 Update-Database // 同步到数据库

批量注册多DbContext

大型项目采用小上下文(一个上下文对应一组业务表),手动注册太繁琐,用反射批量注册:依赖:Zack.Infrastructure

Install-Package Zack.Infrastructure

批量注册代码:

// 扫描BooksEFCore程序集,自动注册所有DbContext builder.Services.AddDbContexts(typeof(MyDbContext).Assembly);

总结

  1. 配置系统:默认多源加载,优先级「命令行 > 环境变量 > 用户机密 > appsettings」,机密信息用用户机密,核心配置用数据库中心化管理;
  2. 项目分层:数据层独立封装实体和上下文,Web 层统一配置和 DI,遵循关注点分离
  3. EF 最佳实践:构造函数注入 Options,用设计时工厂解决多项目迁移问题,避免硬编码配置;
  4. 生产规范:开发环境用用户机密,生产环境用环境变量 / 配置中心,绝不泄露敏感信息。
http://www.jsqmd.com/news/454200/

相关文章:

  • 什么是Lambda表达式,为什么要用Lambda表达式,你在哪里使用过
  • 数据库设计 Step by Step ()
  • 探寻2026年热风干燥机设备系列,江苏靠谱供应商排名 - 工业设备
  • 上海杨浦区擅长大宅整装的公司
  • 口碑好的数字人视频编辑公司
  • 对ScriptableObject做一个评价
  • 教育机构内部账户失陷引发的钓鱼邮件传播机制与防御
  • 非战之罪,从永中Office谈起
  • 2026 年锂电池热点回眸:能量密度、温域、安全与回收五大方向突破
  • 极简部署 OpenClaw 并接入飞书,打造专属 AI 助手
  • ASP.NET MVC随想
  • 2026年标识标牌制作厂家推荐排行榜:不锈钢标识、亚克力标识、铝板标牌、党建医院学校景区系统标识定制,匠心工艺与创新设计典范 - 品牌企业推荐师(官方)
  • 源雀SCRM AI开源版 V2
  • Windows Phone 编程实践—推送通知(剖析推送通知实现架构)
  • 教你秒打造强类型ASP.NET数据绑定
  • 2026上海婚姻家事律师服务优质推荐指南:上海离婚财产分割律师、上海离婚隐匿财产律师、上海继承律师选择指南 - 优质品牌商家
  • 2026 知识付费 SaaS 趋势榜:创客匠人凭全周期适配力登顶,小鹅通等竞品难及
  • 2026复合材料测试新突破:馥勒仪器高低温环境试验机助力航天材料研发 - 品牌推荐大师1
  • 实时数仓的落地路径——从采集到可视化的端到端链路与常见坑
  • 或许你需要一些可操作性更强的实践
  • PowerShell 7使用
  • 研发的那些事--个PM的游戏
  • 2026年江西办公家具品牌制造商性价比对比,鑫恒家具多少钱 - 工业品网
  • Silverlight Beta 新特性预览
  • OS X 上使用.NET开发应用程序
  • 正因为我们是前端,所以代码更需要优雅
  • OpenClaw Windows安装教程:从踩坑到成功,9小时压缩至几步,助你打造私人AI管家!
  • 出身在二三线城市软件工作者的悲哀
  • 我被Claude Code失忆折磨了3天后,写了一个工具拯救自己
  • Hacker传说之不能说的秘密