.NET如何根据数据库类型条件注入/接收依赖服务
解决方案
首先修正你代码中的类型错误:PostgresRepository实现的是IExampleRepository<Guid>,但方法参数和返回类型误用了ObjectId,正确代码如下:
public class PostgresRepository : IExampleRepository<Guid> { public Task<bool> ExistsAsync(Guid id, CancellationToken cancellationToken = default) => Task.FromResult(true); public Task<ExampleEntity<Guid>?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default) => Task.FromResult(null as ExampleEntity<Guid>); }
接下来提供两种依赖注入的实现方案,根据你的业务场景选择:
方案一:单一数据库实例(根据配置动态切换)
如果你的项目一次只使用一种数据库(比如通过配置决定用MongoDB还是Postgres),可以按以下步骤实现:
1. 添加数据库配置
在appsettings.json中添加数据库提供者配置:
{ "Database": { "Provider": "MongoDB" // 可选值:"MongoDB" 或 "Postgres" } }
2. 注册仓储服务
在Program.cs中读取配置,动态注册对应仓储:
var builder = WebApplication.CreateBuilder(args); var dbProvider = builder.Configuration["Database:Provider"]; if (dbProvider == "MongoDB") { builder.Services.AddScoped<IExampleRepository<ObjectId>, MongoRepository>(); } else if (dbProvider == "Postgres") { builder.Services.AddScoped<IExampleRepository<Guid>, PostgresRepository>(); }
3. 控制器接收依赖
控制器需要明确指定仓储的泛型参数类型,对应你配置的数据库:
[ApiController] [Route("[controller]")] public class ExampleController : Controller { // 若配置的是MongoDB,用ObjectId;若为Postgres,用Guid private readonly IExampleRepository<ObjectId> _exampleRepository; public ExampleController(IExampleRepository<ObjectId> exampleRepository) { _exampleRepository = exampleRepository; } [HttpGet("{id}")] public async Task<IActionResult> GetById(string id) { if (!ObjectId.TryParse(id, out var objectId)) { return BadRequest("无效的ObjectId格式"); } var entity = await _exampleRepository.GetByIdAsync(objectId); return Ok(entity); } }
方案二:同时支持多种数据库(工厂模式)
如果需要在项目中同时使用MongoDB和Postgres,可通过工厂模式动态获取对应仓储:
1. 定义仓储工厂接口与实现
public interface IExampleRepositoryFactory { IExampleRepository<TId> GetRepository<TId>(); } public class ExampleRepositoryFactory : IExampleRepositoryFactory { private readonly IServiceProvider _serviceProvider; public ExampleRepositoryFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public IExampleRepository<TId> GetRepository<TId>() { return _serviceProvider.GetRequiredService<IExampleRepository<TId>>(); } }
2. 注册所有仓储与工厂
在Program.cs中注册两种仓储和工厂服务:
var builder = WebApplication.CreateBuilder(args); // 注册两种仓储 builder.Services.AddScoped<IExampleRepository<ObjectId>, MongoRepository>(); builder.Services.AddScoped<IExampleRepository<Guid>, PostgresRepository>(); // 注册工厂 builder.Services.AddScoped<IExampleRepositoryFactory, ExampleRepositoryFactory>();
3. 控制器中使用工厂
[ApiController] [Route("[controller]")] public class ExampleController : Controller { private readonly IExampleRepository<ObjectId> _mongoRepository; private readonly IExampleRepository<Guid> _postgresRepository; public ExampleController(IExampleRepositoryFactory factory) { _mongoRepository = factory.GetRepository<ObjectId>(); _postgresRepository = factory.GetRepository<Guid>(); } [HttpGet("mongo/{id}")] public async Task<IActionResult> GetMongoEntity(string id) { if (!ObjectId.TryParse(id, out var objectId)) { return BadRequest("无效的ObjectId格式"); } var entity = await _mongoRepository.GetByIdAsync(objectId); return Ok(entity); } [HttpGet("postgres/{id:guid}")] public async Task<IActionResult> GetPostgresEntity(Guid id) { var entity = await _postgresRepository.GetByIdAsync(id); return Ok(entity); } }
内容的提问来源于stack exchange,提问作者Vinicius Andrade
相关产品推荐
相关产品推荐

