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

.NET Core 2.0中ADO.NET的依赖注入:连接字符串注入问题求助

嘿,我之前也碰到过类似的情况——放弃EF改用ADO.NET后,确实得调整依赖注入的方式来传递连接字符串,刚好适配你的分层架构,给你几个实用的方案:

方案一:直接注入连接字符串(最简单直接)

先在根MVC项目的Startup.cs里,从配置文件读取连接字符串,再注册到DI容器里:

public void ConfigureServices(IServiceCollection services)
{
    // 从appsettings.json里读你的数据库连接字符串
    var dbConnectionString = Configuration.GetConnectionString("YourDatabase");
    // 字符串是不可变的,注册成单例完全没问题
    services.AddSingleton(dbConnectionString);
    
    // 注册你的仓储类,比如IProductRepository和对应的实现
    services.AddScoped<IProductRepository, ProductRepository>();
    
    // 其他MVC相关配置...
}

然后在核心项目的仓储类里,直接通过构造函数注入这个字符串就行:

public class ProductRepository : IProductRepository
{
    private readonly string _connectionString;

    // 构造函数注入连接字符串
    public ProductRepository(string connectionString)
    {
        _connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
    }

    // 用ADO.NET操作数据库的时候直接用这个字符串
    public async Task<Product> GetProductById(int id)
    {
        using (var conn = new SqlConnection(_connectionString))
        {
            await conn.OpenAsync();
            // 这里写你的SQL命令逻辑...
        }
    }
}

这个方案的好处就是简单直接,不需要额外封装,适合小到中型项目。

方案二:封装成配置类(更规范,方便扩展)

如果之后你可能需要加更多数据库相关配置(比如命令超时时间),可以把这些配置封装成一个类,更符合.NET Core的配置规范:

首先在核心项目里定义配置类:

public class DatabaseConfig
{
    public string ConnectionString { get; set; }
    // 可以加其他配置项,比如默认命令超时
    public int DefaultCommandTimeout { get; set; } = 30;
}

然后在根MVC项目的Startup.cs里绑定配置并注册:

public void ConfigureServices(IServiceCollection services)
{
    // 把appsettings.json里的Database节点绑定到DatabaseConfig
    services.Configure<DatabaseConfig>(Configuration.GetSection("Database"));
    
    // 注册仓储
    services.AddScoped<IProductRepository, ProductRepository>();
    
    // 其他配置...
}

对应的appsettings.json配置大概是这样:

{
  "Database": {
    "ConnectionString": "Server=.;Database=YourDb;Trusted_Connection=True;",
    "DefaultCommandTimeout": 60
  }
}

最后在仓储类里注入IOptions<DatabaseConfig>:

public class ProductRepository : IProductRepository
{
    private readonly DatabaseConfig _dbConfig;

    public ProductRepository(IOptions<DatabaseConfig> dbConfig)
    {
        _dbConfig = dbConfig.Value ?? throw new ArgumentNullException(nameof(dbConfig));
        if (string.IsNullOrEmpty(_dbConfig.ConnectionString))
        {
            throw new ArgumentException("数据库连接字符串不能为空", nameof(dbConfig));
        }
    }

    // 使用的时候就可以拿到所有配置项
    public async Task<IEnumerable<Product>> GetAllProducts()
    {
        using (var conn = new SqlConnection(_dbConfig.ConnectionString))
        {
            conn.CommandTimeout = _dbConfig.DefaultCommandTimeout;
            await conn.OpenAsync();
            // 执行查询逻辑...
        }
    }
}

这个方案扩展性更强,后续加配置项很方便,适合需要多配置的场景。

方案三:注入数据库连接工厂(灵活度更高)

如果你的项目需要更灵活的连接管理——比如不同仓储用不同连接,或者需要统一处理连接的创建逻辑,那可以封装一个连接工厂:

先在核心项目定义接口和实现:

public interface IDbConnectionFactory
{
    IDbConnection CreateConnection();
}

public class SqlServerConnectionFactory : IDbConnectionFactory
{
    private readonly string _connectionString;

    public SqlServerConnectionFactory(string connectionString)
    {
        _connectionString = connectionString;
    }

    public IDbConnection CreateConnection()
    {
        var conn = new SqlConnection(_connectionString);
        // 这里可以统一设置连接的属性,比如超时、编码之类的
        // 也可以选择在这里打开连接,或者让调用者自己打开,看你的需求
        conn.Open();
        return conn;
    }
}

然后在根MVC项目的Startup.cs里注册:

public void ConfigureServices(IServiceCollection services)
{
    var connectionString = Configuration.GetConnectionString("YourDatabase");
    services.AddSingleton<IDbConnectionFactory>(new SqlServerConnectionFactory(connectionString));
    
    services.AddScoped<IProductRepository, ProductRepository>();
}

最后在仓储类里注入这个工厂:

public class ProductRepository : IProductRepository
{
    private readonly IDbConnectionFactory _connectionFactory;

    public ProductRepository(IDbConnectionFactory connectionFactory)
    {
        _connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory));
    }

    public async Task DeleteProduct(int id)
    {
        using (var conn = _connectionFactory.CreateConnection())
        {
            // 执行删除逻辑...
        }
    }
}

这个方案把连接的创建逻辑完全封装起来,仓储不需要关心连接的细节,适合大型项目或者有复杂连接管理需求的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:12:25