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

如何解决无法解析Microsoft.EntityFrameworkCore.IDbContextFactory服务的错误?

解决ASP.NET Core中IDbContextFactory<C4PDbContext>无法解析的依赖注入问题

运行ASP.NET Core项目时触发Unable to resolve service for type 'Microsoft.EntityFrameworkCore.IDbContextFactory<C4PDbContext>'错误,已尝试注册DI容器组件但问题未解决,怀疑ManageUserDocuments中的DbContext配置存在遗漏。以下为项目相关代码、错误信息及解决方案:


项目代码文件

UserService.cs

using Cosmos.UnitsOfWork;
using GraphQlProject.Interfaces;
using GraphQlProject.Models;
using User = Cosmos.Entities.User;

namespace GraphQlProject.Services;

public class UserService : IUser
{
    private readonly IManageUserDocuments _documents;

    public UserService(IManageUserDocuments documents)
    {
        _documents = documents;
    }

    public async Task<Models.User> GetUserById(string id)
    {
        {
            try
            {
                var user = await _documents.UserRepository.GetUserByIdAsync(id);

                var convertedUser = new Models.User
                {
                   // DO SOMETHING
                };
                return convertedUser;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }
    }
}

ManageUserDocuments.cs(IDbContextFactory实现)

using System;
using System.Threading.Tasks;
using Cosmos.EntityFramework;
using Cosmos.Repositories;
using Microsoft.EntityFrameworkCore;

namespace Cosmos.UnitsOfWork;

public interface IManageUserDocuments : IUnitOfWork
{
    public IUserRepository UserRepository { get; }
}

public class ManageUserDocuments : IManageUserDocuments
{
    private IUserRepository? _userRepository;
    private readonly C4PDbContext _c4pDbContext;

    /// <summary>
    ///
    /// </summary>
    /// <param name="dbContextFactory">Instance of a class that implements IDbContextFactory</param>
    /// <exception cref="ArgumentNullException"></exception>
    public ManageUserDocuments(IDbContextFactory<C4PDbContext> dbContextFactory)
    {
        _c4pDbContext =
            dbContextFactory.CreateDbContextAsync().GetAwaiter().GetResult()
            ?? throw new ArgumentNullException(nameof(C4PDbContext));
    }

    private void Dispose(bool disposing)
    {
        if (disposing)
        {
            _c4pDbContext.Dispose();
        }
    }

    public void Dispose()
    {
        Dispose(true);
    }

    public Task<int> SaveChangesAsync()
    {
        return _c4pDbContext.SaveChangesAsync();
    }

    public IUserRepository UserRepository
    {
        get { return _userRepository ??= new UserRepository(_c4pDbContext); }
    }
}

UserRepository.cs

using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
using Cosmos.EntityFramework;
using Microsoft.Azure.Cosmos;
using Microsoft.EntityFrameworkCore;
using User = Cosmos.Entities.User;

namespace Cosmos.Repositories;

public interface IUserRepository
{
    public Task<User> GetUserByIdAsync(string id);
}

public class UserRepository : IUserRepository
{
    private readonly C4PDbContext _c4pDbContext;
    
    public UserRepository(C4PDbContext c4pDbContext)
    {
        _c4pDbContext = c4pDbContext;
    }
    
    public async Task<User> GetUserByIdAsync(string id)
    {
        var partLine = await _c4pDbContext.Database.GetCosmosClient()
            .GetContainer("c4p", nameof(User).ToLower())
            .ReadItemStreamAsync(id, new PartitionKey(id));

        return partLine.IsSuccessStatusCode
            ? await JsonSerializer.DeserializeAsync<User>(partLine.Content)
            : default;
    }
}

C4PDbContext.cs

using Cosmos.Entities;
using Microsoft.EntityFrameworkCore;

namespace Cosmos.EntityFramework;

public class C4PDbContext : DbContext
{
    /// <summary>
    ///     Overloaded constructor
    /// </summary>
    /// <param name="options">Instance of a DbContextOptions</param>
    public C4PDbContext(DbContextOptions<C4PDbContext> options)
        : base(options) { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        #region User

        modelBuilder
            .Entity<User>()
            .ToContainer(nameof(User).ToLower())
            .HasNoDiscriminator()
            .HasPartitionKey(x => x.id);

        #endregion

        base.OnModelCreating(modelBuilder);
    }
}

Program.cs

using System.Runtime.CompilerServices;
using Cosmos.EntityFramework;
using Cosmos.Repositories;
using Cosmos.UnitsOfWork;
using GraphiQl;
using GraphQL.Server;
using GraphQL.Types;
using GraphQlProject.Interfaces;
using GraphQlProject.Mutations;
using GraphQlProject.Query;
using GraphQlProject.Schema;
using GraphQlProject.Services;
using GraphQlProject.Type;
using Microsoft.Azure.Cosmos;
using Microsoft.EntityFrameworkCore.Internal;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();

// Scoped Services
builder.Services.AddTransient<IProduct, ProductService>();
builder.Services.AddTransient<IUser, UserService>();

// Repositories
builder.Services.AddTransient<IUserRepository, UserRepository>();

// DB Context
builder.Services.AddDbContext<C4PDbContext>();

// Register GraphQL type, query and schema
builder.Services.AddSingleton<ProductType>();
builder.Services.AddSingleton<UserType>();

builder.Services.AddSingleton<ProductQuery>();
builder.Services.AddSingleton<UserQuery>();

builder.Services.AddSingleton<ProductMutation>();

builder.Services.AddSingleton<ISchema, ProductSchema>();
builder.Services.AddSingleton<ISchema, UserSchema>();

builder.Services.AddGraphQL(x => x.EnableMetrics = false).AddSystemTextJson();

// Cosmos
// builder.Services.AddSingleton(_ => new CosmosClient(""));

// Units Of Work
builder.Services.AddScoped<IManageUserDocuments, ManageUserDocuments>();
// builder.Services.AddTransient<IManageUserDocuments, ManageUserDocuments>();

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseGraphiQl("/graphql");
app.UseGraphQL<ISchema>();


app.Run();

错误信息

System.AggregateException:部分服务无法构造(验证服务描述符时出错,无法解析Microsoft.EntityFrameworkCore.IDbContextFactory<C4PDbContext>服务以激活ManageUserDocuments)

---> (内部异常 #1) System.InvalidOperationException:验证服务描述符时出错,无法解析Microsoft.EntityFrameworkCore.IDbContextFactory<C4PDbContext>服务以激活ManageUserDocuments

---> (内部异常 #2) System.InvalidOperationException:验证服务描述符时出错,无法解析Microsoft.EntityFrameworkCore.IDbContextFactory<C4PDbContext>服务以激活ManageUserDocuments


解决方案

1. 替换DbContext注册方式为工厂模式

原Program.cs中使用AddDbContext<C4PDbContext>()仅注册了DbContext实例,未注册IDbContextFactory<C4PDbContext>,而ManageUserDocuments的构造函数依赖该工厂。需将DbContext注册代码替换为AddDbContextFactory,并配置Cosmos连接:

// 从配置文件读取Cosmos连接字符串
var cosmosConnectionString = builder.Configuration.GetConnectionString("CosmosDb");

// 注册DbContext工厂
builder.Services.AddDbContextFactory<C4PDbContext>(options =>
{
    options.UseCosmos(cosmosConnectionString, databaseName: "c4p");
});

同时确保appsettings.json中添加对应连接字符串配置:

{
  "ConnectionStrings": {
    "CosmosDb": "你的Cosmos DB连接字符串"
  }
}

2. 修复ManageUserDocuments中的同步阻塞异步问题

原代码中使用dbContextFactory.CreateDbContextAsync().GetAwaiter().GetResult()同步阻塞异步方法,易导致死锁。建议延迟初始化DbContext,调整后的代码如下:

public class ManageUserDocuments : IManageUserDocuments
{
    private IUserRepository? _userRepository;
    private readonly IDbContextFactory<C4PDbContext> _dbContextFactory;
    private C4PDbContext? _c4pDbContext;

    public ManageUserDocuments(IDbContextFactory<C4PDbContext> dbContextFactory)
    {
        _dbContextFactory = dbContextFactory ?? throw new ArgumentNullException(nameof(dbContextFactory));
    }

    // 延迟初始化DbContext,避免构造函数中阻塞异步调用
    private C4PDbContext C4pDbContext => _c4pDbContext ??= _dbContextFactory.CreateDbContext();

    private void Dispose(bool disposing)
    {
        if (disposing)
        {
            _c4pDbContext?.Dispose();
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    public Task<int> SaveChangesAsync()
    {
        return C4pDbContext.SaveChangesAsync();
    }

    public IUserRepository UserRepository
    {
        get { return _userRepository ??= new UserRepository(C4pDbContext); }
    }
}

3. 移除冗余的DbContext注册

替换为AddDbContextFactory后,需删除原有的builder.Services.AddDbContext<C4PDbContext>()代码,避免DI容器出现冲突注册。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 22:24:21