验证服务描述符 'ServiceType: INewsRepository Lifetime: Singleton ImplementationType: NewsRepository' 时出错:
Error while validating the service descriptor 'ServiceType: INewsRepository Lifetime: Singleton ImplementationType: NewsRepository':
我尝试使用存储库模式从我的数据库中获取数据
我有 3 个项目
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
模型项目
中的新闻class
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; }
}
}
模型项目中的上下文 class
namespace bmu.model
{
public class BmuContext : DbContext
{
public BmuContext(DbContextOptions<BmuContext> options): base(options)
{
}
public DbSet<News> News { get; set; }
}
}
我在 Repo 项目中的界面
namespace bmu.repo.Contracts
{
public interface INewsRepository
{
Task<IEnumerable<News>> GetAllAsync();
Task<IEnumerable<News>> GetAllActiveAsync();
}
}
在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();
}
}
}
同时添加
services.AddControllers();
services.AddSingleton<INewsRepository, NewsRepository>();
正在启动 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();
}
}
}
但是当 运行 项目时我得到了这个错误
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'.)
也是因为多项目用这个添加 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);
}
}
}
这个错误有什么解决办法吗?
您的 API 中存在生命周期类型不匹配。 EntityFramework DbContext 是一个范围内的服务,您不能拥有 NewsRepository 的单例实例,因为它依赖于为每个请求生成的实例。
您要么必须将 NewsRepository 用作范围内的服务,要么重组您的依赖项解析,如 SO 答案所示:
首先,你需要改变:
services.AddSingleton<INewsRepository, NewsRepository>();
收件人:
services.AddTransient<INewsRepository, NewsRepository>();
其次,你需要在NewsRepository
中注入IMemoryCache
而不是MemoryCache
。
下面是一个简单的演示:
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;
}
//...
}
是因为
private readonly IMemoryCache _memoryCache;
当我删除它时,每个人都认为工作正常
喜欢 Sotiris Koukios-Panopoulos -san 评论
我看到您只是在为设计时设置选项,而不是在您的 Startup.cs
中。我期待一个:
services.AddDbContext<BmuContext>(options => options.UseSqlite("your connection string"));
相反。
就我而言,我忘记在 Startup.cs
中进行设置
services.AddDbContext<myDbContext>(o => o.UseSqlServer(myConnectionString));
我忘了提这个,因为我正在使用接口服务
services.AddScoped<IMyTruckService, MyTruckService>();
我正在添加正在注入 DbContext
class.
的 singleton
服务
services.AddSingleton<WeatherForecastService>();
我将上面的内容更改为下面的内容(添加了 transient
服务范围)并且有效。
services.AddTransient<FoodItemService>();
我有两个 dbcontext,忘记在 startup.cs 文件中提到这个
services.AddDbContext<Abc>(option => option.UseSqlServer(Configuration.GetConnectionString("ConStr")));
我的错误是我注入了服务class而不是接口
是
//This is wrong
Private readonly DataSerive _dataService;
public void EmployeeHandler(DataSerive dataService)
{
_dataService = dataService;
}
但应该是
//This is correct
Private readonly IDataSerive _dataService;
public void EmployeeHandler(IDataSerive dataService)
{
_dataService = dataService;
}
这里的DataService是处理操作的class
IDataService 是 接口
我尝试使用存储库模式从我的数据库中获取数据 我有 3 个项目
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
模型项目
中的新闻classnamespace 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; }
}
}
模型项目中的上下文 class
namespace bmu.model
{
public class BmuContext : DbContext
{
public BmuContext(DbContextOptions<BmuContext> options): base(options)
{
}
public DbSet<News> News { get; set; }
}
}
我在 Repo 项目中的界面
namespace bmu.repo.Contracts
{
public interface INewsRepository
{
Task<IEnumerable<News>> GetAllAsync();
Task<IEnumerable<News>> GetAllActiveAsync();
}
}
在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();
}
}
}
同时添加
services.AddControllers();
services.AddSingleton<INewsRepository, NewsRepository>();
正在启动 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();
}
}
}
但是当 运行 项目时我得到了这个错误
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'.)
也是因为多项目用这个添加 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);
}
}
}
这个错误有什么解决办法吗?
您的 API 中存在生命周期类型不匹配。 EntityFramework DbContext 是一个范围内的服务,您不能拥有 NewsRepository 的单例实例,因为它依赖于为每个请求生成的实例。
您要么必须将 NewsRepository 用作范围内的服务,要么重组您的依赖项解析,如 SO 答案所示:
首先,你需要改变:
services.AddSingleton<INewsRepository, NewsRepository>();
收件人:
services.AddTransient<INewsRepository, NewsRepository>();
其次,你需要在NewsRepository
中注入IMemoryCache
而不是MemoryCache
。
下面是一个简单的演示:
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;
}
//...
}
是因为
private readonly IMemoryCache _memoryCache;
当我删除它时,每个人都认为工作正常
喜欢 Sotiris Koukios-Panopoulos -san 评论
我看到您只是在为设计时设置选项,而不是在您的 Startup.cs
中。我期待一个:
services.AddDbContext<BmuContext>(options => options.UseSqlite("your connection string"));
相反。
就我而言,我忘记在 Startup.cs
services.AddDbContext<myDbContext>(o => o.UseSqlServer(myConnectionString));
我忘了提这个,因为我正在使用接口服务
services.AddScoped<IMyTruckService, MyTruckService>();
我正在添加正在注入 DbContext
class.
singleton
服务
services.AddSingleton<WeatherForecastService>();
我将上面的内容更改为下面的内容(添加了 transient
服务范围)并且有效。
services.AddTransient<FoodItemService>();
我有两个 dbcontext,忘记在 startup.cs 文件中提到这个
services.AddDbContext<Abc>(option => option.UseSqlServer(Configuration.GetConnectionString("ConStr")));
我的错误是我注入了服务class而不是接口
是
//This is wrong
Private readonly DataSerive _dataService;
public void EmployeeHandler(DataSerive dataService)
{
_dataService = dataService;
}
但应该是
//This is correct
Private readonly IDataSerive _dataService;
public void EmployeeHandler(IDataSerive dataService)
{
_dataService = dataService;
}
这里的DataService是处理操作的class IDataService 是 接口