You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Function无法读取local.settings.json中的环境变量

问题描述

我创建了一个Azure Function,在Program文件中配置了DbContext,并在local.settings.json文件中添加了连接字符串。

如图所示,调用Environment.GetEnvironmentVariable("TaskDbConnection")返回了null值,我期望该方法能返回local.settings.json文件中配置的对应值。

配置截图1
调试截图2

以下是Program.CS代码:

var builder = Host.CreateDefaultBuilder(args)
    .ConfigureFunctionsWebApplication((host, webApp) =>
    {
        StartupHelper.FunctionsWorkerDefaults(webApp
            , host
            , "Sentry DSN");

        webApp.UseMiddleware<TaskRequestAuditMiddleware>();
    });

//builder.ConfigureFunctionsWebApplication();

// Application Insights isn't enabled by default. See https://aka.ms/AAt8mw4.
// builder.Services
//     .AddApplicationInsightsTelemetryWorkerService()
//     .ConfigureFunctionsApplicationInsights();

builder.ConfigureServices(services =>
{
    // 1. Setup EF Core with Audit.Net
    var tdbcs = Environment.GetEnvironmentVariable("TaskDbConnection");
    services.AddDbContext<TaskDbContext>(options => {
        options.UseSqlServer(tdbcs);

#if DEBUG
        options.EnableSensitiveDataLogging();
#endif
    });

    var idbcs = Environment.GetEnvironmentVariable("InsightsConnection");
    services.AddDbContextFactory<TaskInsightsDbContext>(options =>
    {
        options.UseSqlServer(idbcs);

#if DEBUG
        options.EnableSensitiveDataLogging();
#endif
    });

    // 2. Add MediatR (scan the application layer for commands, queries, and event handlers)
    services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(CreateTaskCommandHandler).Assembly));  // Point to the assembly where MediatR handlers are located
    services.AddScoped<ITaskReadOnlyRepository, TaskRepository>();
    services.AddScoped<ITaskWriteOnlyRepository, TaskRepository>();

    services.AddScoped<IDomainEventDispatcher, DomainEventDispatcher>();
    services.AddScoped<IDomainEventPublisher, RabbitMqEventPublisher>();

    // 3. Configure Audit.Net
    Audit.EntityFramework.Configuration.Setup()
     .ForContext<TaskDbContext>(config => config
         .IncludeEntityObjects()
         .AuditEventType("{context}:{database}"))
     .UseOptOut()
         .IgnoreAny(t => t.Name.EndsWith("Audit"));


    Audit.Core.Configuration.Setup()
        .UseEntityFramework(ef => ef
            .AuditTypeExplicitMapper(m =>
            {
                // Example: Add types that should be audited
                m.Map<GoalCrusher.Backend.Task.Infrastructure.Entities.Task, TaskAudit>();  // Audit user entity
                m.Map<Subtask, SubtaskAudit>();  // Audit user entity
                m.Map<Note, NoteAudit>();  // Audit user entity
                m.AuditEntityAction<IAudit>((evt, entry, auditEntity) =>
                {
                    // Customize the audit event with additional information
                    auditEntity.AuditAction = entry.Action;
                    auditEntity.AuditDate = DateTimeOffset.Now;
                    auditEntity.AuditEventDocument = evt.ToJson();
                    //auditEntity.CorrelationId = evt.CustomFields["CorrelationId"].ToString().ToGuid();// as Guid;
                    auditEntity.AuditorUserId = evt.CustomFields["AuditorUserId"]?.ToString();
                    auditEntity.CorrelationId = evt.CustomFields["CorrelationId"]?.ToString();
                });
            }));

    // Configure Audit.Net
    Audit.Core.Configuration.AddCustomAction(ActionType.OnEventSaving, scope =>
    {
        // Set the custom fields in the audit event
        scope.SetCustomField("AuditorUserId", AuditContext.UserId ?? "Anonymous");
        scope.SetCustomField("CorrelationId", AuditContext.CorrelationId ?? "No Correlation Id");

        if (scope.Event.Environment.Exception != null)
        {
            scope.SetCustomField("ExceptionMessage", scope.Event.Environment.Exception);
        }

        scope.Comment("Saved at " + DateTimeOffset.Now);
    });

    // 4. Register any additional services here
    // Example: Logging
    services.AddLogging(loggingBuilder =>
    {
        var cs = Environment.GetEnvironmentVariable("InsightsConnection");
        loggingBuilder.AddConsole();  // Logs to the console
        StartupHelper.SetupSerilog(loggingBuilder
            , "task_insights"
            ,connectionString:cs );
    });
});

builder.Build().Run();
解决方法

1. 检查local.settings.json结构

Azure Functions的配置项必须放在Values节点下,确保你的配置文件格式正确:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
    "TaskDbConnection": "你的SQL Server连接字符串",
    "InsightsConnection": "你的Insights连接字符串"
  }
}

2. 确保配置文件被复制到输出目录

右键local.settings.json → 属性 → 设置复制到输出目录为如果较新则复制或始终复制,避免调试时程序读取不到配置文件。

3. 改用IConfiguration读取配置

在.NET Isolated模式的Azure Function中,Environment.GetEnvironmentVariable可能因配置加载时机问题读取不到值,推荐通过IConfiguration读取:

builder.ConfigureServices((context, services) =>
{
    // 通过context.Configuration获取配置
    var tdbcs = context.Configuration["TaskDbConnection"];
    services.AddDbContext<TaskDbContext>(options => {
        options.UseSqlServer(tdbcs);

#if DEBUG
        options.EnableSensitiveDataLogging();
#endif
    });

    var idbcs = context.Configuration["InsightsConnection"];
    services.AddDbContextFactory<TaskInsightsDbContext>(options =>
    {
        options.UseSqlServer(idbcs);

#if DEBUG
        options.EnableSensitiveDataLogging();
#endif
    });

    // 其余服务配置保持不变...
});

4. 清理并重启调试

清理项目(右键项目 → 清理)后重启调试器,确保配置变更被重新加载。

内容的提问来源于stack exchange,提问作者ChampChris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 19:04:52