You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core 5中如何在静态方法中注入Database对象?

可行解决方案

方案一:将查询逻辑抽离为仓储类(推荐)

把实体类的查询逻辑移到专门的仓储类中,让实体仅作为数据载体,避免业务逻辑与实体耦合,同时完美适配依赖注入。

  1. 定义仓储接口:
public interface IPersonRepository
{
    IEnumerable<Person> GetAll();
}
  1. 实现仓储类,注入IDatabase:
public class PersonRepository : IPersonRepository
{
    private readonly IDatabase _database;

    public PersonRepository(IDatabase database)
    {
        _database = database;
    }

    public IEnumerable<Person> GetAll()
    {
        using var connection = _database.GetConnection();
        return connection.Query<Person>("SELECT * FROM Persons");
    }
}
  1. 在Startup.cs中注入仓储:
services.AddScoped<IPersonRepository, PersonRepository>();
  1. 使用时直接注入IPersonRepository调用即可,比如在控制器中:
public class PersonController : Controller
{
    private readonly IPersonRepository _personRepo;

    public PersonController(IPersonRepository personRepo)
    {
        _personRepo = personRepo;
    }

    public IActionResult Index()
    {
        var persons = _personRepo.GetAll();
        return View(persons);
    }
}

这个方案符合单一职责原则,实体类只负责存储数据,查询逻辑由仓储类处理,完全避开了Dapper对实体构造的限制。

方案二:给静态查询方法传入IDatabase实例

如果坚持要在实体类中保留查询方法,可以修改静态方法,让调用者传入已注入的IDatabase实例,这样既不破坏实体的无参构造(满足Dapper要求),又能使用依赖注入的连接。

修改Person类的静态方法:

public class Person
{
    // 实体属性
    public int Id { get; set; }
    public string Name { get; set; }

    public static IEnumerable<Person> GetAll(IDatabase database)
    {
        using var connection = database.GetConnection();
        return connection.Query<Person>("SELECT * FROM Persons");
    }
}

调用时,从依赖注入容器中获取IDatabase传入:

// 比如在控制器中
public class PersonController : Controller
{
    private readonly IDatabase _database;

    public PersonController(IDatabase database)
    {
        _database = database;
    }

    public IActionResult Index()
    {
        var persons = Person.GetAll(_database);
        return View(persons);
    }
}

这个方案保留了实体类中的查询逻辑,同时避免了硬编码连接字符串,也不影响Dapper的实体映射。

方案三:使用服务定位器(应急方案,不推荐)

如果以上两种方案都无法满足需求,可以临时使用服务定位器模式,从DI容器中直接获取IDatabase实例,但这种方式会让代码耦合DI容器,不利于测试和维护,仅作为应急手段。

  1. 在Program.cs中保存服务提供者(.NET Core 5的Program结构):
public static class Program
{
    public static IServiceProvider ServiceProvider { get; private set; }

    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();
        ServiceProvider = host.Services;
        host.Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    }
}
  1. 在Person类的静态方法中获取IDatabase:
public static IEnumerable<Person> GetAll()
{
    using var scope = Program.ServiceProvider.CreateScope();
    var database = scope.ServiceProvider.GetRequiredService<IDatabase>();
    using var connection = database.GetConnection();
    return connection.Query<Person>("SELECT * FROM Persons");
}

注意:必须创建作用域(CreateScope)来获取Scoped生命周期的IDatabase,否则会导致生命周期管理问题。


内容的提问来源于stack exchange,提问作者Ahmad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 16:32:50