在ASP.NET Core中高效安全地连接数据库并读取数据是开发Web应用的核心能力,以下是基于ADO.NET的专业实现方案,遵循最佳实践确保性能与安全:

环境准备与配置
-
引用必要NuGet包
Install-Package System.Data.SqlClient # SQL Server # 或 Install-Package MySql.Data # MySQL
-
配置连接字符串 (appsettings.json)
{ "ConnectionStrings": { "DefaultConnection": "Server=.;Database=YourDB;User Id=sa;Password=YourPwd;Encrypt=True;TrustServerCertificate=True;" } }
分层架构实现(推荐)
数据访问层 (DAL)
public class ProductRepository
{
private readonly IConfiguration _config;
public ProductRepository(IConfiguration config)
{
_config = config;
}
public List<Product> GetProducts()
{
var products = new List<Product>();
// 使用using确保资源释放
using (var conn = new SqlConnection(
_config.GetConnectionString("DefaultConnection")))
{
// 参数化查询防SQL注入
var sql = "SELECT ProductId, Name, Price FROM Products WHERE Stock > @MinStock";
using (var cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@MinStock", 10);
conn.Open();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
products.Add(new Product()
{
Id = reader.GetInt32(0),
Name = reader.GetString(1),
Price = reader.GetDecimal(2)
});
}
}
}
}
return products;
}
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
服务层调用 (Service Layer)
public class ProductService
{
private readonly ProductRepository _repo;
public ProductService(ProductRepository repo)
{
_repo = repo;
}
public IEnumerable<Product> GetAvailableProducts()
{
return _repo.GetProducts();
}
}
控制器注入 (Controller)

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly ProductService _service;
public ProductsController(ProductService service)
{
_service = service;
}
[HttpGet]
public IActionResult Get()
{
return Ok(_service.GetAvailableProducts());
}
}
关键安全与性能优化
-
防御性编程
- 参数化查询:彻底杜绝SQL注入
- 连接池:默认启用,通过
Pooling=true控制 - 错误日志:捕获
SqlException并记录
-
异步操作提升吞吐量
public async Task<List<Product>> GetProductsAsync() { using (var conn = new SqlConnection(_config.GetConnectionString("DefaultConnection"))) { await conn.OpenAsync(); using (var cmd = new SqlCommand("SELECT...", conn)) { using (var reader = await cmd.ExecuteReaderAsync()) { // 异步读取逻辑 } } } } -
企业级扩展方案
- ORM选择:Entity Framework Core(复杂业务场景)
- Dapper:高性能微ORM(适合读密集型操作)
- 连接管理:使用
IDbConnectionFactory
不同数据库适配方案
| 数据库类型 | 连接包 | 连接字符串示例 |
|---|---|---|
| SQL Server | System.Data.SqlClient | Server=.;Database=DB;User=sa;Pwd=xxx; |
| MySQL | MySql.Data | Server=localhost;Database=DB;Uid=root;Pwd=xxx; |
| PostgreSQL | Npgsql | Host=localhost;Database=DB;Username=postgres;Password=xxx; |
常见陷阱解决方案
-
连接泄露
- 错误:未调用
Dispose() - 修复:严格使用
using块
- 错误:未调用
-
密码硬编码

- 错误:代码中写死连接串
- 修复:通过
IConfiguration注入 + 使用Azure Key Vault
-
查询超时
- 错误:复杂查询未设超时
- 修复:
cmd.CommandTimeout = 30;
架构师建议:在微服务场景下,建议将数据库访问封装为独立服务,通过gRPC或REST API提供数据,对于高并发读取,可引入Redis缓存查询结果,响应速度可提升10倍以上。
互动讨论:你在实际项目中如何处理分库分表的数据读取?是否遇到过连接池耗尽的情况?欢迎在评论区分享你的实战经验与解决方案!
原创文章,作者:世雄 - 原生数据库架构专家,如若转载,请注明出处:https://idctop.com/article/18825.html