Error while validating the service descriptor 'ServiceType: INewsRepository Lifetime: Singleton ImplementationType: NewsRepository':
Asked Answered
K

12

36

I try get data from my database with repository Pattern i have 3 project

Bmu.Mode 'this is for model to create database'

Bmu.Repo 'it have 2 folder for repository include contract/InewsRepository.cs' and 'Repository/NewsRepository' for implement Interface

Bmu.Api for invoke data from Repo project

news class in Model Project

namespace bmu.model
{
   public class News
   {
    public int Id { get; set; }

    public string SubTitle { get; set; }

    public string Title { get; set; }

    public string Summery { get; set; }
  }
}

context class in model project

namespace bmu.model
 {
   public class BmuContext : DbContext
    {
       public BmuContext(DbContextOptions<BmuContext> options): base(options)
      {

      }
    public DbSet<News> News { get; set; }
   }
}

My interface in Repo project

namespace bmu.repo.Contracts
{
  public interface INewsRepository
  {
    Task<IEnumerable<News>> GetAllAsync();
    Task<IEnumerable<News>> GetAllActiveAsync();
  }
}

implement interface in bmu.repo

namespace bmu.repo.IRepository
{
 public class NewsRepository : INewsRepository
 {
    private readonly BmuContext _context;
    private readonly MemoryCache _memoryCache;

    public NewsRepository(BmuContext context, MemoryCache memoryCache)
    {
        _context = context;
        _memoryCache = memoryCache;
    }
    public async Task<IEnumerable<News>> GetAllAsync()
    {
        return await _context.News.ToListAsync(); 
    }
    public async Task<IEnumerable<News>> GetAllActiveAsync()
    {
      return   await _context.News.Where(x => x.Active).ToListAsync();
    }

}
}

Also add

services.AddControllers(); 
        services.AddSingleton<INewsRepository, NewsRepository>();

in startup of Api project and this is my controller

namespace bmu.api.Controllers
{
[ApiController]
[Route("[controller]")]
public class NewsController : ControllerBase
{
     private readonly ILogger<NewsController> _logger;
     private readonly INewsRepository _newsRepository;

    public NewsController(ILogger<NewsController> logger,INewsRepository newsRepository)
    {
        _logger = logger;
        _newsRepository = newsRepository; 
    }
    [HttpGet]
    public async Task<IEnumerable<News>> Get()
    {
        return await _newsRepository.GetAllActiveAsync();
    }
}
}

but when run project i got this error

AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: bmu.repo.Contracts.INewsRepository Lifetime: Singleton ImplementationType: bmu.repo.IRepository.NewsRepository': Unable to resolve service for type 'bmu.model.BmuContext' while attempting to activate 'bmu.repo.IRepository.NewsRepository'.)

also because of multi project add DbContext with this

UPDATE:

namespace bmu.model
{
public class BmuContextFactory : IDesignTimeDbContextFactory<BmuContext>
{
    public BmuContext CreateDbContext(string[] args)
    {
        var optionsBuilder = new DbContextOptionsBuilder<BmuContext>();
        optionsBuilder.UseSqlite("Data Source=bmu.db");

        return new BmuContext(optionsBuilder.Options);
    }
}
}

Is there any solution for this error ?

Kaiak answered 13/12, 2019 at 19:3 Comment(0)
K
-11

It was because of

    private readonly IMemoryCache _memoryCache;

when i remove it every think work fine

Kaiak answered 4/1, 2020 at 20:38 Comment(5)
Your answer is not logical.Hanser
I think its because of don't register IMemoryCache in startup.cs in service, it logicalKaiak
Is IMemoryCache was registerd in startup.cs?Honshu
Also, you should sign Rena's answer as an accepted answerBenbow
I'd also add to @malik comment: You should sign Rena's answer as an accepted answer.Impersonality
O
32

Firstly,you need to change:

services.AddSingleton<INewsRepository, NewsRepository>();

To:

services.AddTransient<INewsRepository, NewsRepository>();

Secondly,you need to inject IMemoryCache instead of MemoryCache in NewsRepository.

Here is a simple demo like below:

1.Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddSession();
    services.AddTransient<INewsRepository, NewsRepository>();
    services.AddDbContext<BmuContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("Connectionstring")));
    services.AddMemoryCache();
}

2.appsettings.json:

"ConnectionStrings": {
    "Connectionstring": "Server=(localdb)\\mssqllocaldb;Database=Bmu;Trusted_Connection=True;MultipleActiveResultSets=true"  
}

3.NewsRepository:

public class NewsRepository : INewsRepository
{
    private readonly BmuContext _context;
    private readonly IMemoryCache _memoryCache;

    public NewsRepository(BmuContext context, IMemoryCache memoryCache)
    {
        _context = context;
    }
    //...
}
Olsewski answered 16/12, 2019 at 9:9 Comment(3)
I do All of think, remove " private readonly IMemoryCache _memoryCache;" from Repository and avery think work fineKaiak
In my case, i created non-public constructor. Resolved by creating it public and it works.Volumed
It would be nice if you explained what was wrong instead of just issuing instructions.Tricksy
T
27

My Error was that I was injecting the service class instead of the interface

It was

  //This is wrong
Private readonly DataSerive _dataService;
public void EmployeeHandler(DataSerive dataService)
{
_dataService = dataService;
}

But it should be

 //This is correct
Private readonly IDataSerive _dataService;
public void EmployeeHandler(IDataSerive dataService)
{
_dataService = dataService;
}

Here DataService is the class that handles operation and IDataService is the interface

Tod answered 16/9, 2021 at 12:25 Comment(1)
this. chances are you need to use the interface instead of the class, or vice versa. In my case I needed to implement ILogger<T> instead of Logger<T>Empale
P
10

There is a lifetime type mismatch in your API. EntityFramework DbContext is a scoped service, and you cannot have a singleton instance of the NewsRepository, as it depends on an instance that is generated for each request.

You either have to use NewsRepository as a scoped service, or restructure your dependency resolution, like shown in this SO answer: Use DbContext in ASP .Net Singleton Injected Class

Pinto answered 13/12, 2019 at 19:23 Comment(4)
I use services.AddScoped<INewsRepository, NewsRepository>();but get this error againKaiak
How are you registering your BmuContext?Pinto
services.AddDbContext<BmuContext>(); Also update my questionKaiak
I see you are only setting up the options for designtime, not in your Startup.cs. I expect a services.AddDbContext<BmuContext>(options => options.UseSqlite(your connection string)); insteadPinto
R
4

Like Sotiris Koukios-Panopoulos -san comment

I see you are only setting up the options for design time, not in your Startup.cs. I expect a:

services.AddDbContext<BmuContext>(options => options.UseSqlite("your connection string"));

instead.

In my case, I forgot to set this in my Startup.cs

services.AddDbContext<myDbContext>(o => o.UseSqlServer(myConnectionString));

and I forgot to mention this, because I'm using interface an service

services.AddScoped<IMyTruckService, MyTruckService>();
Russian answered 8/3, 2020 at 20:11 Comment(0)
I
3

The issue for me was that alluded to in @sotiris-panopoulos alternative.

see if bmu.repo.Contracts.INewsRepository has a reference to another object that ALSO must be a part of your buider.

In my app, I was having this issue on

builder.Services.AddScoped<ShiftMessageDetailService>();

In my ShiftMessageDetailService there I'm using a IDbContextFactory object

 private IDbContextFactory<ApplicationDbContext> _dbContextFactory;

So there is a Service type "Mismatch" because the ShiftMessageDetailService is scoped, and the ApplicationDbContext is null

so, the fix for me was also build the AddDbContextFactory. It did fix the problem, the part I'm a bit confused is AddDbContextFactory scoped or transient or singleton - or is that dynamic? I'm not sure but it just can't be null and the issue went away.

builder.Services.AddDbContextFactory<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("LCPVconnection")));
builder.Services.AddScoped<ShiftMessageDetailService>();
Imagism answered 25/5, 2023 at 11:36 Comment(0)
I
2

I was adding singleton service that was injecting DbContext class.

services.AddSingleton<WeatherForecastService>();

I changed above to below (Added a transient service scope) and it worked.

services.AddTransient<FoodItemService>();
Irritability answered 25/6, 2020 at 19:58 Comment(0)
A
1

This error can be caused by circular dependency. Because probably, you inject service1 in service2 and also service2 in service1. You should change it and break circular dependency.

Amoakuh answered 6/6, 2022 at 5:40 Comment(0)
B
0

I was having two dbcontext, and forgotten to mention this in startup.cs file

services.AddDbContext<Abc>(option => option.UseSqlServer(Configuration.GetConnectionString("ConStr")));
Barbary answered 25/5, 2021 at 7:29 Comment(1)
Welcome to SO. its not clear if your post is answering the original question. If you believe your post answers it, please elaborate why and how with more detailYonyona
S
0

In my case, I created a constructor method in my service by accident:


public class NewsRepository: INewsRepository 
{
    public NewsRepository(INewsRepository newsRepository)
    {
    // code ....        
    }
// code ....
 }

This generates circular dependency and a lot of trouble.

Subassembly answered 3/12, 2023 at 4:29 Comment(0)
L
0

I solved it by doing this:

    services.AddScoped<IDummyRepository, DummyRepository>();
    services.AddHostedService<TestBackgroundService >();

and then

public class TestBackgroundService : BackgroundService
{
    private readonly IServiceScopeFactory _scopeFactory;

    public TestBackgroundService(IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // here is the magic 
        using (var scope = _scopeFactory.CreateScope())
        {
            var dummyRepository = scope.ServiceProvider.GetRequiredService<IDummyRepository>();
            
            dummyRepository.DoWork();
        }
    }
}
Liard answered 20/12, 2023 at 19:22 Comment(0)
M
-1

Have a nice time

To solve this problem, it is enough to change the way of calling the DB context in the interface

Example:

  private readonly DataBaseContext _context;
    public TestRepository(DataBaseContext context)
    {
        _context = context;
    }

To:

private readonly DataBaseContext _context;
        public TestRepository()
        {
            _context = new DataBaseContext();
        }

I am Farhad Rezvani from Iran.

Minaret answered 22/6, 2023 at 21:54 Comment(0)
K
-11

It was because of

    private readonly IMemoryCache _memoryCache;

when i remove it every think work fine

Kaiak answered 4/1, 2020 at 20:38 Comment(5)
Your answer is not logical.Hanser
I think its because of don't register IMemoryCache in startup.cs in service, it logicalKaiak
Is IMemoryCache was registerd in startup.cs?Honshu
Also, you should sign Rena's answer as an accepted answerBenbow
I'd also add to @malik comment: You should sign Rena's answer as an accepted answer.Impersonality

© 2022 - 2024 — McMap. All rights reserved.