ASP.NET Core 2 Unable to resolve service for type Microsoft EntityFrameworkCore DbContext

此生再无相见时 提交于 2019-12-03 17:26:33

问题


When I run my asp.net core 2 projects I get the following error message:

InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContext' while attempting to activate 'ContosoUniversity.Service.Class.StudentService'.

Here is my project structure:

-- solution 'ContosoUniversity'
----- ContosoUniversity
----- ContosoUniversity.Model
----- ContosoUniversity.Service

IEntityService (related code) :

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

IEntityService (related code) :

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>();
    }
}

Entity :

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);
}

StudentService :

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; }
}

And finally here is my Startup.cs class :

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?}");
        });
    }
}

What should I do to resolve this problem?


回答1:


StudentService expects DbContext but the container does not know how to resolve it based on your current startup.

You would need to either explicitly add the context to the service collection

Startup

services.AddScoped<DbContext, SchoolContext>();
services.AddScoped<IStudentService, StudentService>();

Or update the StudentService constructor to explicitly expect a type the container knows how to resolve.

StudentService

public StudentService(SchoolContext context)
    : base(context)
{ 
    //...
}



回答2:


if dbcontext inherited from system.data.entity.DbContext then it woud be added like that

    services.AddScoped(provider => new CDRContext());

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



回答3:


I encountered a similar error i.e.

An unhandled exception occurred while processing the request. InvalidOperationException: Unable to resolve service for type 'MyProjectName.Models.myDatabaseContext' while attempting to activate 'MyProjectName.Controllers.MyUsersController'.

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

What I later figured out was... I was missing the following line i.e. adding my database context to services:

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

Here goes my ConfigureServices method defined in Startup class:

 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;"));

                }
        ...
        ...
    }

Basically, when you generated model classes from database, all your database tables were mapped into respective Model classes by creating the "New Scaffolded Item" and choosing the appropriate database context during the scaffolding procedure. Now, you need to manually register your database context as a service to the services parameter of ConfigureServices method.

Btw, rather than hard coding your connection string, you'll ideally pick it up from the configuration data. I have attempted to keep things simple here.



来源:https://stackoverflow.com/questions/46320189/asp-net-core-2-unable-to-resolve-service-for-type-microsoft-entityframeworkcore

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!