Skip to content

依赖注入

在 ASP.NET Core 中,推荐把数据库连接注册成仓储的依赖。AddDbConnection<TRepository> 会同时注册 IDatabaseRegistry 和你的仓储实例。

安装包

powershell
Install-Package IceCoffee.Db4Net.DependencyInjection

如果你的项目还没有对应的数据库驱动,也请一并安装,例如 Microsoft.Data.SqliteMicrosoft.Data.SqlClientNpgsql

定义仓储

csharp
public sealed class ProdRepository : Repository
{
    public ProdRepository(string databaseName) : base(databaseName)
    {
    }

    // 如果你想显式接收 registry,也可以提供这个构造器:
    // public ProdRepository(IDatabaseRegistry registry, string databaseName) : base(registry, databaseName)
    // {
    // }
}

容器会优先使用 (IDatabaseRegistry, string) 构造器;如果没有,再回退到 (string) 构造器。

配置服务

csharp
builder.Services.AddDbConnection<ProdRepository>("ProdDatabaseName", options =>
{
    options.DatabaseProvider = DatabaseProvider.SQLite;
    options.ConnectionString = configuration.GetConnectionString("ProdDatabase")
        ?? throw new InvalidOperationException("Missing connection string: ProdDatabase");
});

如果你更喜欢从配置节绑定,也可以直接把 IConfiguration 传进去:

csharp
builder.Services.AddDbConnection<ProdRepository>("ProdDatabaseName", builder.Configuration.GetSection("DbConnections:Prod"));

在 API 控制器中使用

csharp
[ApiController]
[Route("[controller]")]
public class FooController : ControllerBase
{
    private readonly ProdRepository _prodRepository;

    public FooController(ProdRepository prodRepository)
    {
        _prodRepository = prodRepository;
    }

    [HttpPost]
    public async Task<ActionResult<Foo>> Create([FromBody] FooDto dto)
    {
        var entity = new Foo
        {
            Name = dto.Name,
            Age = dto.Age
        };

        var id = await _prodRepository.InsertAndGetId(entity).ExecuteAsync<int>();
        entity.Id = id;

        return CreatedAtAction(nameof(Get), new { id }, entity);
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<Foo>> Get([FromRoute] int id)
    {
        var entity = await _prodRepository.Query(id).GetSingleOrDefaultAsync();
        if (entity is null)
        {
            return NotFound();
        }

        return Ok(entity);
    }

    [HttpPut("{id}")]
    public async Task<ActionResult> Update(int id, [FromBody] FooDto dto)
    {
        var entity = await _prodRepository.Query(id).GetSingleOrDefaultAsync();
        if (entity is null)
        {
            return NotFound();
        }

        entity.Name = dto.Name;
        entity.Age = dto.Age;

        await _prodRepository.Update(entity).ExecuteAsync();

        return NoContent();
    }

    [HttpDelete("{id}")]
    public async Task<ActionResult> Delete(int id)
    {
        var entity = await _prodRepository.Query(id).GetSingleOrDefaultAsync();
        if (entity is null)
        {
            return NotFound();
        }

        await _prodRepository.Delete(entity).ExecuteAsync();

        return NoContent();
    }
}

如果你的应用只有一个默认数据库,也可以把仓储注册成默认数据库;如果你有多个库,只要给每个仓储一个不同的数据库名即可。