Blazor服务中DbContext注入空引用异常问题求助
Blazor服务中EF Core数据库操作空引用问题排查与解决
问题描述
尝试在Blazor服务(非组件)中执行数据库插入操作,无论使用DbContext还是DbContextFactory,均出现DbContext空对象引用错误,怀疑问题出在ConsoleWebhookReceiver服务的依赖注入环节。已尝试配置DbContext、DbContextFactory,调整多种启动配置,有无仓储模式都试过。作为Blazor新手,不确定是否仅能在服务器端进行Entity Framework依赖注入,是否需要编写API控制器处理该操作,但认为Webhook接收器中做数据库插入应是简单操作,应该遗漏了某个细节。
相关代码
Program.cs
using BlazorApp.Services; using BotTrading.Controllers; using BotTrading.Data; using BotTrading.Services; using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); builder.Services.AddSingleton<WeatherForecastService>(); builder.Services.AddScoped<IReceiveWebhook, ConsoleWebhookReceiver>(); builder.Services.AddScoped<IWebhookService, WebhookService>(); builder.Services.AddScoped<WebhookService>(); // 重复注册,可移除 builder.Services.AddControllers(); builder.Services.AddDbContextFactory<AppDBContext>(options => options .EnableSensitiveDataLogging() .UseSqlite(builder.Configuration.GetConnectionString("Database"))); var app = builder.Build(); // 这里直接获取服务可能引发问题,建议移除,或通过作用域获取 // var webhookService = app.Services.GetRequiredService<WebhookService>(); // var cryptoService = app.Services.GetRequiredService<CryptoService>(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.MapControllers(); app.UseRouting(); app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); //Listen for POST webhooks app.MapPost("/webhooks", async (HttpContext context, IReceiveWebhook receiveWebook) => { using StreamReader stream = new StreamReader(context.Request.Body); return await receiveWebook.ProcessRequest(await stream.ReadToEndAsync()); }); app.Run();
ConsoleWebhookReceiver.cs
public class ConsoleWebhookReceiver : IReceiveWebhook { private readonly IWebhookService _webhookService; // 通过构造函数注入依赖,避免手动实例化服务 public ConsoleWebhookReceiver(IWebhookService webhookService) { _webhookService = webhookService; } /// <summary> /// 写入POST请求体到控制台,返回JSON并插入数据库 /// </summary> public async Task<string> ProcessRequest(string requestBody) { Console.WriteLine($"Request Body: {requestBody}"); Webhook item = JsonConvert.DeserializeObject<Webhook>(requestBody); // 使用注入的服务执行数据库操作,用await避免死锁 await _webhookService.CreateWebhook(item); Webhook webhook = await _webhookService.GetWebhookById(1); return "{\"message\" : \"Thanks! We got your webhook\"}"; } }
IReceiveWebhook.cs
namespace BlazorApp.Services { public interface IReceiveWebhook { Task<string> ProcessRequest(string requestBody); } }
WebhookService.cs
using System; using System.Collections.Generic; using System.Threading.Tasks; using BotTrading.Data; using BotTrading.Services; using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; namespace BlazorApp.Services { public class WebhookService : IWebhookService { private readonly IDbContextFactory<AppDBContext> _contextFactory; // 统一使用DbContextFactory构造函数 public WebhookService(IDbContextFactory<AppDBContext> contextFactory) { _contextFactory = contextFactory; } public async Task<List<Webhook>> GetWebhookList() { using (var context = await _contextFactory.CreateDbContextAsync()) { return await context.Webhooks.ToListAsync(); } } public async Task<Webhook> GetWebhookById(int id) { using (var context = await _contextFactory.CreateDbContextAsync()) { return await context.Webhooks.FirstOrDefaultAsync(x => x.Id == id); } } public async Task<Webhook> CreateWebhook(Webhook webhook) { using (var context = await _contextFactory.CreateDbContextAsync()) { Console.WriteLine("webhook: " + webhook.Base); await context.Webhooks.AddAsync(webhook); await context.SaveChangesAsync(); return webhook; } } public async Task UpdateWebhook(Webhook webhook) { using (var context = _contextFactory.CreateDbContext()) { context.Webhooks.Update(webhook); await context.SaveChangesAsync(); } } public async Task DeleteWebhook(Webhook webhook) { using (var context = _contextFactory.CreateDbContext()) { context.Webhooks.Remove(webhook); await context.SaveChangesAsync(); } } } }
IWebhookService.cs
using BotTrading.Data; using System.Collections.Generic; using System.Threading.Tasks; namespace BotTrading.Services; public interface IWebhookService { Task<List<Webhook>> GetWebhookList(); Task<Webhook> GetWebhookById(int id); Task<Webhook> CreateWebhook(Webhook webhook); Task UpdateWebhook(Webhook webhook); Task DeleteWebhook(Webhook webhook); }
AppDBContext.cs
using Microsoft.EntityFrameworkCore; namespace BotTrading.Data; public class AppDBContext : DbContext { public AppDBContext(DbContextOptions<AppDBContext> options) : base(options) { } // 移除冗余的OnConfiguring配置,依赖Program.cs中传入的DbContextOptions // protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) // { // optionsBuilder // .EnableSensitiveDataLogging() // .EnableDetailedErrors() // .LogTo(Console.WriteLine, new[] { DbLoggerCategory.Infrastructure.Name }) // .UseSqlite(Configuration.GetConnectionString("Database")); // } public DbSet<Crypto> Cryptos { get; set; } public DbSet<Trade> Trades { get; set; } public DbSet<Webhook> Webhooks { get; set; } }
异常信息
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] An unhandled exception has occurred while executing the request. System.NullReferenceException: Object reference not set to an instance of an object. at BotTrading.Controllers.ConsoleWebhookReceiver.ProcessRequest(String requestBody) at Program.<>c.<<$>b__0_2>d.MoveNext() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Http.RequestDelegateFactory.g__ExecuteAwaited|134_0(Task`1 task, HttpContext httpContext) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
问题根源与解决步骤
核心问题
- ConsoleWebhookReceiver未注入依赖:类中声明的依赖字段未通过构造函数接收DI容器实例,导致调用时出现空引用。
- WebhookService依赖混乱:注释了
IDbContextFactory构造函数,改用AppDBContext构造,但方法内仍使用未初始化的_contextFactory字段。 - 手动实例化服务:直接
new WebhookService绕过DI容器,且使用.Result会引发死锁风险。 - AppDBContext配置错误:
OnConfiguring中使用未注入的Configuration字段,同时重复配置数据库连接。
解决步骤
- 修复ConsoleWebhookReceiver的依赖注入:添加构造函数注入
IWebhookService,移除手动实例化代码,用await替代.Result。 - 统一WebhookService依赖:启用
IDbContextFactory构造函数,确保所有方法使用工厂创建的DbContext。 - 清理AppDBContext:移除未注入的
Configuration字段和冗余的OnConfiguring方法,依赖DbContextOptions传入的配置。 - 优化服务注册:移除重复的
WebhookService注册,避免启动时直接获取服务。
内容的提问来源于stack exchange,提问作者Snowelle
相关产品推荐
相关产品推荐

