一、数据库连接基础
1.1 ADO.NET架构概述
ADO.NET是.NET平台数据访问的核心组件,主要包含:
- Connection:建立与数据库的连接
- Command:执行SQL命令
- DataReader:高效读取数据
- DataAdapter:数据库与DataSet之间的桥梁
- DataSet:内存中的数据库表示
1.2 .NET数据提供程序
数据库类型 | 提供程序命名空间 | 程序集 |
---|---|---|
SQL Server | System.Data.SqlClient | System.Data.SqlClient |
Oracle | Oracle.ManagedDataAccess.Client | Oracle.ManagedDataAccess |
MySQL | MySql.Data.MySqlClient | MySql.Data |
PostgreSQL | Npgsql | Npgsql |
SQLite | Microsoft.Data.Sqlite | Microsoft.Data.Sqlite |
二、SQL Server连接实战
2.1 基本连接步骤
using System.Data.SqlClient;
// 连接字符串示例(实际使用时应加密或从配置读取)
string connectionString = "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;";
// 创建连接对象
using (SqlConnection connection = new SqlConnection(connectionString))
{
try
{
// 打开连接
connection.Open();
Console.WriteLine("连接成功!");
// 执行数据库操作...
}
catch (SqlException ex)
{
Console.WriteLine($"数据库错误: {ex.Message}");
}
// using块结束会自动关闭连接
}
2.2 参数化查询(防止SQL注入)
string productName = "笔记本电脑";
decimal price = 5999.99m;
using (SqlConnection connection = new SqlConnection(connectionString))
{
string sql = "INSERT INTO Products (Name, Price) VALUES (@name, @price)";
using (SqlCommand command = new SqlCommand(sql, connection))
{
// 添加参数
command.Parameters.AddWithValue("@name", productName);
command.Parameters.AddWithValue("@price", price);
connection.Open();
int rowsAffected = command.ExecuteNonQuery();
Console.WriteLine($"插入了 {rowsAffected} 行数据");
}
}
三、使用Entity Framework Core
3.1 ORM基础配置
// 安装NuGet包:Microsoft.EntityFrameworkCore.SqlServer
public class ApplicationDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=MyShopDB;Trusted_Connection=True;");
}
}
// 实体类示例
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
3.2 基本CRUD操作
// 添加数据
using (var context = new ApplicationDbContext())
{
var product = new Product { Name = "无线鼠标", Price = 129.99m };
context.Products.Add(product);
context.SaveChanges();
}
// 查询数据
using (var context = new ApplicationDbContext())
{
var expensiveProducts = context.Products
.Where(p => p.Price > 500)
.OrderByDescending(p => p.Price)
.ToList();
foreach (var product in expensiveProducts)
{
Console.WriteLine($"{product.Name} - {product.Price:C}");
}
}
四、连接池与性能优化
4.1 连接字符串配置选项
"Server=myServer;Database=myDB;User ID=myUser;Password=myPwd;
Max Pool Size=100; // 最大连接数
Min Pool Size=5; // 最小连接数
Connection Timeout=30; // 连接超时(秒)
Pooling=true; // 启用连接池
MultipleActiveResultSets=true" // 启用MARS
4.2 最佳实践
- 及时释放连接资源
// 正确做法 - 使用using语句
using (SqlConnection connection = new SqlConnection(connectionString))
{
// 操作数据库
}
- 避免频繁开关连接
// 执行多个操作时保持连接打开
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
// 操作1
// 操作2
// ...
}
- 使用异步方法处理高并发
public async Task<List<Product>> GetProductsAsync()
{
using (var connection = new SqlConnection(connectionString))
{
await connection.OpenAsync();
return await connection.QueryAsync<Product>(
"SELECT * FROM Products WHERE Price > @minPrice",
new { minPrice = 100 });
}
}
五、多数据库支持
5.1 使用Dapper轻量级ORM
// 安装NuGet包:Dapper
using Dapper;
public class ProductRepository
{
private readonly string _connectionString;
public ProductRepository(string connectionString)
{
_connectionString = connectionString;
}
public IEnumerable<Product> GetProducts(int categoryId)
{
using (var connection = new SqlConnection(_connectionString))
{
return connection.Query<Product>(
"SELECT * FROM Products WHERE CategoryId = @catId",
new { catId = categoryId });
}
}
}
5.2 数据库无关抽象
public interface IDatabaseConnection
{
IEnumerable<T> Query<T>(string sql, object parameters = null);
int Execute(string sql, object parameters = null);
}
// SQL Server实现
public class SqlServerConnection : IDatabaseConnection
{
private readonly string _connectionString;
public SqlServerConnection(string connectionString)
{
_connectionString = connectionString;
}
public IEnumerable<T> Query<T>(string sql, object parameters = null)
{
using (var connection = new SqlConnection(_connectionString))
{
return connection.Query<T>(sql, parameters);
}
}
// 其他方法实现...
}
六、安全注意事项
6.1 连接字符串安全
- 不要硬编码连接字符串
// 正确做法:从配置读取
var connectionString = Configuration.GetConnectionString("DefaultConnection");
- 使用Windows身份验证
"Server=myServer;Database=myDB;Integrated Security=True;"
- 生产环境使用加密存储
6.2 SQL注入防护
- 始终使用参数化查询
// 错误做法(易受SQL注入攻击)
string sql = $"SELECT * FROM Users WHERE Name = '{userInput}'";
// 正确做法
string sql = "SELECT * FROM Users WHERE Name = @name";
command.Parameters.AddWithValue("@name", userInput);
- 使用ORM或查询构建器
七、常见问题解决
7.1 连接超时问题
// 增加连接超时时间
"Server=myServer;Database=myDB;User ID=myUser;Password=myPwd;Connect Timeout=60;"
// 代码中设置Command超时
using (var command = new SqlCommand(sql, connection))
{
command.CommandTimeout = 120; // 秒
// 执行命令
}
7.2 连接泄漏检测
// 在连接字符串中添加以下参数监控连接泄漏
"Application Name=MyApp;Pooling=true;Max Pool Size=100;Connection Lifetime=30"
八、现代数据库访问模式
8.1 仓储模式实现
public interface IRepository<T> where T : class
{
Task<T> GetByIdAsync(int id);
Task<IEnumerable<T>> GetAllAsync();
Task AddAsync(T entity);
Task UpdateAsync(T entity);
Task DeleteAsync(T entity);
}
public class ProductRepository : IRepository<Product>
{
private readonly ApplicationDbContext _context;
public ProductRepository(ApplicationDbContext context)
{
_context = context;
}
public async Task<Product> GetByIdAsync(int id)
{
return await _context.Products.FindAsync(id);
}
// 其他方法实现...
}
8.2 使用依赖注入
// 在Startup.cs中配置
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddScoped<IRepository<Product>, ProductRepository>();
}
// 在控制器中使用
public class ProductsController : Controller
{
private readonly IRepository<Product> _productRepository;
public ProductsController(IRepository<Product> productRepository)
{
_productRepository = productRepository;
}
public async Task<IActionResult> Index()
{
var products = await _productRepository.GetAllAsync();
return View(products);
}
}
结语
本教程涵盖了C#数据库连接的核心技术,从基础的ADO.NET到现代ORM框架。关键要点包括:
- 理解不同数据访问技术的适用场景
- ADO.NET:精细控制、高性能需求
- EF Core:快速开发、复杂领域模型
- Dapper:简单查询、轻量级ORM
- 掌握连接管理的最佳实践
- 正确管理连接生命周期
- 合理配置连接池
- 使用异步方法提高吞吐量
- 重视数据访问安全
- 保护连接字符串
- 防止SQL注入
- 实施适当的访问控制
随着.NET生态的发展,数据库访问技术也在不断演进。建议开发者:
- 关注Entity Framework Core的最新功能
- 了解云原生数据库访问模式
- 学习分布式事务处理
- 掌握性能调优技术
通过本教程的学习,您应该能够根据项目需求选择合适的数据访问策略,构建高效、安全的数据库应用程序。