验证服务描述符“ServiceType: INewsRepository Lifetime: Singleton ImplementationType: NewsRepository”时出错:

sun*_*nny 11 c# repository repository-pattern asp.net-core-mvc asp.net-core-3.0

我尝试使用存储库模式从我的数据库中获取数据我有 3 个项目

Bmu.Mode '这是用于创建数据库的模型'

Bmu.Repo '它有 2 个文件夹用于存储库,包括 contract/InewsRepository.cs' 和用于实现接口的 'Repository/NewsRepository'

Bmu.Api 用于从 Repo 项目调用数据

模型项目中的新闻类

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; }
  }
}
Run Code Online (Sandbox Code Playgroud)

模型项目中的上下文类

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

      }
    public DbSet<News> News { get; set; }
   }
}
Run Code Online (Sandbox Code Playgroud)

我在 Repo 项目中的界面

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

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

}
}
Run Code Online (Sandbox Code Playgroud)

还添加

services.AddControllers(); 
        services.AddSingleton<INewsRepository, NewsRepository>();
Run Code Online (Sandbox Code Playgroud)

在 Api 项目启动时,这是我的控制器

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();
    }
}
}
Run Code Online (Sandbox Code Playgroud)

但是当运行项目时我收到了这个错误

AggregateException:无法构建某些服务(验证服务描述符“ServiceType:bmu.repo.Contracts.INewsRepository Lifetime:Singleton ImplementationType:bmu.repo.IRepository.NewsRepository”时出错:无法解析“bmu”类型的服务。 model.BmuContext' 同时尝试激活 'bmu.repo.IRepository.NewsRepository'。)

也因为多项目添加 DbContext 与此

更新:

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);
    }
}
}
Run Code Online (Sandbox Code Playgroud)

这个错误有什么解决办法吗?

小智 23

我的错误是我注入的是服务类而不是接口

它是

  //This is wrong
Private readonly DataSerive _dataService;
public void EmployeeHandler(DataSerive dataService)
{
_dataService = dataService;
}
Run Code Online (Sandbox Code Playgroud)

但应该是

 //This is correct
Private readonly IDataSerive _dataService;
public void EmployeeHandler(IDataSerive dataService)
{
_dataService = dataService;
}
Run Code Online (Sandbox Code Playgroud)

这里DataService是处理操作的类, IDataService接口


Ren*_*ena 18

首先,您需要更改:

services.AddSingleton<INewsRepository, NewsRepository>();
Run Code Online (Sandbox Code Playgroud)

到:

services.AddTransient<INewsRepository, NewsRepository>();
Run Code Online (Sandbox Code Playgroud)

其次,你需要注入IMemoryCache而不是MemoryCachein NewsRepository

这是一个简单的演示,如下所示:

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();
}
Run Code Online (Sandbox Code Playgroud)

2.appsettings.json:

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

3.新闻库:

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

    public NewsRepository(BmuContext context, IMemoryCache memoryCache)
    {
        _context = context;
    }
    //...
}
Run Code Online (Sandbox Code Playgroud)

  • 如果我的回答有帮助,您可以[接受为答案](https://meta.stackexchange.com/a/5235/673311)吗? (3认同)

小智 10

您的 API 中存在生命周期类型不匹配。EntityFramework DbContext 是一个范围服务,您不能拥有 NewsRepository 的单例实例,因为它依赖于为每个请求生成的实例。

您要么必须使用 NewsRepository 作为范围服务,要么重新构建您的依赖关系解析,如以下 SO 答案所示:Use DbContext in ASP .Net Singleton Injected Class


sun*_*nny -11

原来是因为

    private readonly IMemoryCache _memoryCache;
Run Code Online (Sandbox Code Playgroud)

当我删除它时,每个人都认为工作正常

  • 你的回答不符合逻辑。 (5认同)