stef000
stef000

Reputation: 123

C# Dependency Injection with WEB/API

A colleague of mine and I have been working on a school project and it was suggested to us by the teacher to use dependency injection. However, we get an error that we are unable to resolve due to dependency injection. We built a C# API with React and are using Dotnet Core 3.1 with the EF-core framework. We built the app with the unit of work and generic repository pattern.

Our IUnitOfWork looks like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace _Backend_Jelly_.Repositories
{
    public interface IUnitOfWork : IDisposable
    {
        IUserRepository User { get;  }
        IProjectRepository Project { get; }

        Task<int> Complete();
        void Dispose();
    }
}

And is implemented like this:

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace _Backend_Jelly_.Repositories
{
    public class UnitOfWork : IUnitOfWork
    {
        private readonly DbContext _context;

        public UnitOfWork(DbContext context)
        {
            _context = context;
            User = new UserRepository(_context);
            Project = new ProjectRepository(_context);
        }
        public IUserRepository User { get; private set; }
        public IProjectRepository Project { get; private set; }

        public async Task<int> Complete()
        {
            return await _context.SaveChangesAsync();
        }

        public async void Dispose() => await _context.DisposeAsync();
    }
}

The generic Repository should have the DBContext injected like this:

protected  DbContext _context;
protected readonly DbSet<TEntity> _set;
public Repository(DbContext context)
{
    _context = context;
    _set = _context.Set<TEntity>();
}

And our Controllers depend on an instance of UnitOfWork:

private readonly IUnitOfWork _unitOfWork;

public ProjectController(IUnitOfWork unitOfWork)
{
    _unitOfWork = unitOfWork;
}

And in the Startup we inject the DBContext and our UnitOfWork:

services.AddDbContext<JellyContext>(opts => opts.UseLazyLoadingProxies().UseMySql(Configuration["ConnectionString:JellyDB"]));
services.AddScoped<IUnitOfWork, UnitOfWork>();

The application throws an error enter image description here

Full errormessage:

System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: _Backend_Jelly_.Repositories.IUnitOfWork Lifetime: Scoped ImplementationType: _Backend_Jelly_.Repositories.UnitOfWork': Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContext' while attempting to activate '_Backend_Jelly_.Repositories.UnitOfWork'.)'

InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContext' while attempting to activate '_Backend_Jelly_.Repositories.UnitOfWork'.

and we are not quite sure why.

Upvotes: 1

Views: 661

Answers (1)

Nkosi
Nkosi

Reputation: 247018

The issue is most likely that the container does not know how to handle DbContext as constructor parameter since only JellyContext is what is registered.

Either update the dependent class to explicitly depend on what is actually needed and registered with the IoC container

//...

private readonly JellyContext _context;

public UnitOfWork(JellyContext context) {
    _context = context;
    User = new UserRepository(_context);
    Project = new ProjectRepository(_context);
}

//...

Or update the service registration accordingly so the container knows how to handle DbContext injected explicitly

services.AddDbContext<DbContext, JellyContext>(opts =>
    opts.UseLazyLoadingProxies().UseMySql(Configuration["ConnectionString:JellyDB"]));

Upvotes: 2

Related Questions