ASP.NET Core中WebApiTestContext服务无法解析问题求助
问题描述
我是ASP.NET新手,正在开发一个Hello World级别的GET API,目标是从MySQL数据库获取数据并返回给客户端。
我使用以下命令生成DbContext及相关文件:
dotnet ef dbcontext scaffold "Server=localhost;Database=webApiTest;User Id=root;Password=000;" Microsoft.EntityFrameworkCore.SqlServer -o Models/
由于项目默认没有Startup.cs,我手动创建该文件以将自动生成的WebApiTestContext注册为依赖服务:
using Microsoft.EntityFrameworkCore; using WebApplication3.Models; namespace WebApplication3; public class Startup { private readonly IConfiguration _configuration; public Startup(IConfiguration configuration) { _configuration = configuration; } public void ConfigureServices(IServiceCollection services) { services.AddDbContext<WebApiTestContext>(options => options.UseMySQL(_configuration.GetConnectionString("YourConnectionString"))); } }
UserController通过依赖注入使用WebApiTestContext:
using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using WebApplication3.DTO; using WebApplication3.Models; namespace WebApplication3.Controllers; [ApiController] [Route("api/[controller]")] public class UserController : ControllerBase { private readonly WebApiTestContext dbContext; public UserController(WebApiTestContext dbContext) { this.dbContext = dbContext; } [HttpGet("GetUsers")] public async Task<ActionResult<List<UserDTO>>> Get() { var List = await dbContext.Users.Select(s=> new UserDTO { Id = s.Id, FirstName = s.FirstName, LastName = s.LastName, UserName = s.Username, Password = s.Password, EnrollmentDate = s.EnrollmentDate, }).ToListAsync(); if (List.Count < 0) { return NotFound(); } return List; } }
自动生成的WebApiTestContext代码如下:
using System; using System.Collections.Generic; using Microsoft.EntityFrameworkCore; namespace WebApplication3.Models; public partial class WebApiTestContext : DbContext { public WebApiTestContext() { } public WebApiTestContext(DbContextOptions<WebApiTestContext> options) : base(options) { } public virtual DbSet<User> Users { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) #warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263. => optionsBuilder.UseMySQL("Server=localhost;Database=webApiTest;User Id=root;Password=000;"); protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>(entity => { entity.HasKey(e => e.Id).HasName("PRIMARY"); entity.ToTable("user"); entity.Property(e => e.EnrollmentDate).HasColumnType("datetime"); entity.Property(e => e.FirstName).HasMaxLength(45); entity.Property(e => e.LastName).HasMaxLength(45); entity.Property(e => e.Password).HasMaxLength(45); entity.Property(e => e.Username).HasMaxLength(45); }); OnModelCreatingPartial(modelBuilder); } partial void OnModelCreatingPartial(ModelBuilder modelBuilder); }
运行时出现如下错误:
System.InvalidOperationException: Unable to resolve service for type 'WebApplication3.Models.WebApiTestContext' while attempting to activate 'WebApplication3.Controllers.UserController'.
解决方案
1. 修正EF Core脚手架命令,重新生成DbContext
你使用了SQL Server的EF Core Provider(Microsoft.EntityFrameworkCore.SqlServer)连接MySQL,这会导致生成的DbContext不兼容。需要改用MySQL专用的Pomelo EF Core Provider:
首先安装依赖包:
dotnet add package Pomelo.EntityFrameworkCore.MySql dotnet add package Microsoft.EntityFrameworkCore.Design
然后重新执行脚手架命令:
dotnet ef dbcontext scaffold "Server=localhost;Database=webApiTest;User Id=root;Password=000;" Pomelo.EntityFrameworkCore.MySql -o Models/
2. 移除手动创建的Startup.cs,在Program.cs中注册DbContext
.NET 6及以后版本默认使用顶级语句,不再需要单独的Startup.cs,手动创建的Startup.cs不会被框架自动加载,这是依赖注入失败的核心原因。
打开Program.cs,添加DbContext注册代码:
var builder = WebApplication.CreateBuilder(args); // 注册DbContext,替换为你的MySQL版本 builder.Services.AddDbContext<WebApplication3.Models.WebApiTestContext>(options => options.UseMySql(builder.Configuration.GetConnectionString("WebApiTest"), new MySqlServerVersion(new Version(8, 0, 36)))); // 添加控制器服务 builder.Services.AddControllers(); var app = builder.Build(); // 配置HTTP管道 app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
3. 在appsettings.json中配置连接字符串
打开appsettings.json,添加连接字符串节点:
{ "ConnectionStrings": { "WebApiTest": "Server=localhost;Database=webApiTest;User Id=root;Password=000;" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
4. 清理WebApiTestContext中的硬编码连接字符串
自动生成的DbContext中,OnConfiguring方法的硬编码连接字符串会覆盖依赖注入的配置,修改为仅在未配置时生效:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { #warning 请将连接字符串移出源代码以保护敏感信息 optionsBuilder.UseMySql("Server=localhost;Database=webApiTest;User Id=root;Password=000;", new MySqlServerVersion(new Version(8, 0, 36))); } }
5. 修正UserController中的逻辑错误
List.Count < 0永远为false(集合Count不可能为负数),改为判断集合是否为空:
[HttpGet("GetUsers")] public async Task<ActionResult<List<UserDTO>>> Get() { var userList = await dbContext.Users.Select(s=> new UserDTO { Id = s.Id, FirstName = s.FirstName, LastName = s.LastName, UserName = s.Username, Password = s.Password, EnrollmentDate = s.EnrollmentDate, }).ToListAsync(); if (!userList.Any()) { return NotFound(); } return userList; }
内容的提问来源于stack exchange,提问作者S k
相关产品推荐
相关产品推荐

