ASP.NET Core 2无法解析Microsoft EntityFrameworkCore DbContext类型的服务。

32
当我运行我的asp.net core 2项目时,我会收到以下错误消息:
InvalidOperationException: 在尝试激活“ContosoUniversity.Service.Class.StudentService”时无法解析类型为“Microsoft.EntityFrameworkCore.DbContext”的服务。
这是我的项目结构:
-- solution 'ContosoUniversity'
----- ContosoUniversity
----- ContosoUniversity.Model
----- ContosoUniversity.Service

IEntityService (related code) :

public interface IEntityService<T> : IService
 where T : BaseEntity
{
    Task<List<T>> GetAllAsync();      
}

IEntityService(相关代码):


public abstract class EntityService<T> : IEntityService<T> where T : BaseEntity
{
    protected DbContext _context;
    protected DbSet<T> _dbset;

    public EntityService(DbContext context)
    {
        _context = context;
        _dbset = _context.Set<T>();
    }

    public async virtual Task<List<T>> GetAllAsync()
    {
        return await _dbset.ToListAsync<T>();
    }
}

实体:

public abstract class BaseEntity { 

}

public abstract class Entity<T> : BaseEntity, IEntity<T> 
{
    public virtual T Id { get; set; }
}

IStudentService :

public interface IStudentService : IEntityService<Student>
{
    Task<Student> GetById(int Id);
}

学生服务:

public class StudentService : EntityService<Student>, IStudentService
{
    DbContext _context;

    public StudentService(DbContext context)
        : base(context)
    {
        _context = context;
        _dbset = _context.Set<Student>();
    }

    public async Task<Student> GetById(int Id)
    {
        return await _dbset.FirstOrDefaultAsync(x => x.Id == Id);
    }
}

SchoolContext :

public class SchoolContext : DbContext
{
    public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
    {
    }

    public DbSet<Course> Courses { get; set; }
    public DbSet<Enrollment> Enrollments { get; set; }
    public DbSet<Student> Students { get; set; }
}

最后,这是我的Startup.cs类:

public class Startup
{
    public Startup(IConfiguration configuration, IHostingEnvironment env, IServiceProvider serviceProvider)
    {
        Configuration = configuration;

        var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);


        Configuration = builder.Build();

    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<SchoolContext>(option =>
            option.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));


        services.AddScoped<IStudentService, StudentService>();

        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

我该怎么做来解决这个问题?

2
AddDbContext<SchoolContext> 只会注册你特定的 DbContext,即 SchoolContext,而不包括它的基类。建议尝试搜索相关信息。 - CodeCaster
4个回答

66

StudentService 需要 DbContext,但是容器无法根据当前的启动程序解析它。

您需要将上下文显式添加到服务集合中。

Startup

services.AddScoped<DbContext, SchoolContext>();
services.AddScoped<IStudentService, StudentService>();
< p > < strong > 或者 更新 StudentService 构造函数,明确地期望容器知道如何解析的类型。 < /p > < p > < em > StudentService < /p >
public StudentService(SchoolContext context)
    : base(context)
{ 
    //...
}

请问如何使用 services.AddScoped<DbContext, SchoolContext>();,如果我有多个数据库上下文 SchoolContextTrainingContext - Anyname Donotcare
@任意名称不在乎,您需要具有区分抽象或更新工厂委托以明确解析目标服务所需的上下文。 - Nkosi
这个对 AddDbContextFactory 也适用吗?也就是说,我是否需要添加一个特定的作用域服务来正确地生成 DbContext 实现的工厂?这个问题展示了我的意思。 - intcreator

6

我遇到了类似的错误:

处理请求时发生未处理异常。InvalidOperationException: 在尝试激活'MyProjectName.Controllers.MyUsersController'时,无法解析类型为'MyProjectName.Models.myDatabaseContext'的服务。

Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, bool isDefaultParameterRequired)

后来我发现,我缺少以下代码行,即将我的数据库上下文添加到服务中:

services.AddDbContext<yourDbContext>(option => option.UseSqlServer("Server=Your-Server-Name\\SQLExpress;Database=yourDatabaseName;Trusted_Connection=True;"));

这里是我在Startup类中定义的ConfigureServices方法:

 public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential 
                //cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddDbContext<yourDbContext>(option => 
            option.UseSqlServer("Server=Your-Server-Name\\SQLExpress;Database=yourDatabaseName;Trusted_Connection=True;"));

                }
        ...
        ...
    }

基本上,当你从数据库生成模型类时,通过创建"New Scaffolded Item"并在脚手架过程中选择相应的数据库上下文,所有数据库表都将映射到各自的模型类中。现在,你需要手动将你的数据库上下文注册为ConfigureServices方法的services参数的服务。

顺便提一下,最好不要硬编码你的连接字符串,最好是从配置数据中获取。我试图让事情变得简单一些。


4
如果dbcontext继承自system.data.entity.DbContext,那么它会像这样被添加。
    services.AddScoped(provider => new CDRContext());

    services.AddTransient<IUnitOfWork, UnitOfWorker>();
    services.AddTransient<ICallService, CallService>();

1
当options参数为空或无法使用GetConnectionString()检索时,将引发此错误。
我的appsettings.json文件定义了我的ConnectionStrings,但末尾多了一个花括号},导致出现了这个错误。
很傻,但令人沮丧。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接