在C# WinForms开发中,数据库操作是核心功能之一。以下从基础到进阶详细解析四大数据库操作(Insert/Update/Delete/Select),包含安全防护、性能优化和最佳实践:
一、连接数据库基础
// 使用现代连接字符串配置(App.config)
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=.;Initial Catalog=YourDB;Integrated Security=SSPI;Connect Timeout=30;Encrypt=True;TrustServerCertificate=True"
providerName="System.Data.SqlClient"/>
</connectionStrings>
// 使用Using语句确保资源释放
using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString))
{
conn.Open(); // 显式打开连接
// 数据库操作...
}
二、参数化查询与SQL注入防护
所有操作必须使用参数化查询,禁止字符串拼接:
var cmd = new SqlCommand("INSERT INTO Users (Name, Age) VALUES (@Name, @Age)", conn);
cmd.Parameters.Add("@Name", SqlDbType.NVarChar, 50).Value = txtName.Text;
cmd.Parameters.Add("@Age", SqlDbType.Int).Value = int.Parse(txtAge.Text);
三、四大操作深度解析
1. INSERT 操作
// 获取自增ID(OUTPUT INSERTED)
string sql = @"INSERT INTO Products (Name, Price)
OUTPUT INSERTED.Id
VALUES (@Name, @Price)";
using (var cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@Name", productName);
cmd.Parameters.AddWithValue("@Price", price);
int newId = (int)cmd.ExecuteScalar(); // 获取新插入记录的ID
}
2. UPDATE 操作
// 带事务的更新
using (var transaction = conn.BeginTransaction())
{
try
{
string sql = @"UPDATE Orders
SET Status = @NewStatus
WHERE Id = @OrderId AND Status = @OldStatus";
var cmd = new SqlCommand(sql, conn, transaction);
cmd.Parameters.AddWithValue("@NewStatus", newStatus);
cmd.Parameters.AddWithValue("@OrderId", orderId);
cmd.Parameters.AddWithValue("@OldStatus", oldStatus);
int affected = cmd.ExecuteNonQuery();
if (affected == 0)
{
throw new Exception("更新条件不匹配或记录不存在");
}
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
3. DELETE 操作
// 软删除实践
string sql = @"UPDATE Users
SET IsDeleted = 1, DeleteTime = GETDATE()
WHERE Id = @UserId";
// 代替物理删除
// 使用存储过程增强权限控制
var cmd = new SqlCommand("sp_DeleteUser", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@UserId", userId);
4. SELECT 操作
// 分页查询(SQL Server 2012+)
string sql = @"SELECT *
FROM Sales
ORDER BY SaleDate DESC
OFFSET @PageSize * (@PageNumber - 1) ROWS
FETCH NEXT @PageSize ROWS ONLY";
using (var cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@PageSize", pageSize);
cmd.Parameters.AddWithValue("@PageNumber", pageNumber);
var adapter = new SqlDataAdapter(cmd);
var dataTable = new DataTable();
adapter.Fill(dataTable);
// 绑定到DataGridView
dgvSales.DataSource = dataTable;
}
四、进阶技巧
1. 批量操作优化
// 使用SqlBulkCopy进行大数据插入
using (var bulkCopy = new SqlBulkCopy(conn))
{
bulkCopy.DestinationTableName = "Logs";
bulkCopy.BatchSize = 5000; // 每批5000条
bulkCopy.WriteToServer(logDataTable); // DataTable数据源
}
2. 异步操作
// 异步查询避免UI冻结
async Task LoadDataAsync()
{
using (var conn = new SqlConnection(connectionString))
{
await conn.OpenAsync();
var cmd = new SqlCommand("SELECT * FROM LargeTable", conn);
using (var reader = await cmd.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
// 异步处理数据...
}
}
}
}
3. ORM整合(Dapper示例)
// 使用微型ORM提升开发效率
public IEnumerable<User> GetActiveUsers()
{
using (var conn = new SqlConnection(connectionString))
{
return conn.Query<User>(
"SELECT * FROM Users WHERE IsActive = @IsActive",
new { IsActive = true });
}
}
五、安全与性能要点
-
防御性编程:
- 始终验证用户输入(如int.TryParse处理数值)
- 限制数据库用户权限(禁止SA账户直连)
- 日志记录敏感操作
-
连接池优化:
- 默认开启连接池(max pool size=100)
- 及时释放连接(避免using嵌套不当)
-
查询性能:
- 为常用WHERE条件字段建立索引
- 避免SELECT *,明确指定字段
- 使用EXPLAIN分析查询计划
-
错误处理:
try { // 数据库操作 } catch (SqlException ex) when (ex.Number == 547) { // 外键约束错误特殊处理 } catch (SqlException ex) { // 记录错误日志 Logger.Error(ex, "数据库操作失败"); }
六、架构建议
- 采用Repository模式解耦数据访问
- 使用DTO进行数据传输
- 依赖注入管理数据库上下文
- 单元测试策略(使用内存数据库或Mock)
完整示例项目结构:
/MyApp
/Models
User.cs
Order.cs
/Repositories
IUserRepository.cs
UserRepository.cs
/Services
UserService.cs
App.config
MainForm.cs
通过分层架构实现高可维护性,每个数据库操作应:
- 验证业务规则
- 记录审计日志
- 处理并发冲突
- 保证事务一致性