1. 环境准备与基础概念在开始动手之前我们需要确保开发环境已经准备就绪。首先需要安装Visual Studio建议2019或2022版本这是开发WPF应用的标准IDE。同时确保本地或远程已经部署了SQL Server数据库服务我推荐使用SQL Server 2019 Express版它对个人开发者完全免费。很多新手容易忽略一个关键点数据库连接本质上是通过网络协议进行的通信。就像我们用微信发送消息需要对方的微信号一样连接数据库也需要几个基本信息服务器地址可以是IP或主机名、数据库名称、登录账号和密码。这里有个小技巧如果连接本地数据库服务器地址可以简写为(local)或者一个点.这比写localhost更简洁。注意在实际项目中千万不要像示例代码那样把连接字符串明文写在代码里我们稍后会讲解如何安全地存储数据库凭据。2. 建立数据库连接2.1 连接字符串详解连接字符串是通往数据库的钥匙它的基本格式是这样的string connStr ServermyServerAddress;DatabasemyDataBase;User IdmyUsername;PasswordmyPassword;;每个参数都有讲究Server不仅支持IP地址也可以填主机名Database要连接的具体数据库名称User Id/Password建议使用专门的数据库账号而非sa超级管理员还可以添加Connect Timeout30来控制连接超时时间我遇到过不少连接失败的情况90%的问题都出在连接字符串上。建议先用SQL Server Management Studio测试连接确保参数正确后再写到代码中。2.2 使用SqlConnection对象创建连接对象的正确姿势应该是这样using (SqlConnection conn new SqlConnection(connStr)) { try { conn.Open(); // 这里执行数据库操作 } catch (SqlException ex) { MessageBox.Show($连接失败{ex.Message}); } }这里有几个关键点一定要用using语句包裹确保连接会被自动关闭Open()方法会实际建立连接可能抛出异常连接是稀缺资源用完要及时释放我曾经在一个项目中忘记关闭连接结果导致数据库连接池耗尽整个系统卡死。这个教训让我养成了总是使用using块的好习惯。3. 实现CRUD操作3.1 增删改操作(ExecuteNonQuery)对于插入、更新和删除操作我们使用ExecuteNonQuery方法。这里以插入数据为例string sql INSERT INTO Users (Name, Age) VALUES (name, age); using (SqlCommand cmd new SqlCommand(sql, conn)) { cmd.Parameters.AddWithValue(name, 张三); cmd.Parameters.AddWithValue(age, 25); int rowsAffected cmd.ExecuteNonQuery(); Console.WriteLine($影响了{rowsAffected}行数据); }特别注意一定要使用参数化查询避免SQL注入攻击name这种参数名可以自定义但前后要一致ExecuteNonQuery返回受影响的行数可以用来验证操作是否成功3.2 查询操作(ExecuteReader)查询数据稍微复杂些需要用到SqlDataReaderstring sql SELECT Id, Name, Age FROM Users WHERE Age minAge; using (SqlCommand cmd new SqlCommand(sql, conn)) { cmd.Parameters.AddWithValue(minAge, 18); using (SqlDataReader reader cmd.ExecuteReader()) { while (reader.Read()) { int id reader.GetInt32(0); string name reader.GetString(1); int age reader.GetInt32(2); Console.WriteLine(${id}: {name}, {age}岁); } } }这里有几个实用技巧按列索引读取比按列名读取效率更高记得检查reader.HasRows判断是否有数据可以用reader.GetOrdinal(列名)先获取列索引4. WPF界面与数据绑定4.1 设计基础界面在MainWindow.xaml中我们可以设计一个简单的数据管理界面Grid DataGrid x:NameusersGrid AutoGenerateColumnsFalse Margin10 DataGrid.Columns DataGridTextColumn HeaderID Binding{Binding Id}/ DataGridTextColumn Header姓名 Binding{Binding Name}/ DataGridTextColumn Header年龄 Binding{Binding Age}/ /DataGrid.Columns /DataGrid StackPanel OrientationHorizontal VerticalAlignmentBottom Margin10 Button Content刷新 ClickRefreshData_Click Width80 Margin5/ Button Content新增 ClickAddUser_Click Width80 Margin5/ Button Content删除 ClickDeleteUser_Click Width80 Margin5/ /StackPanel /Grid4.2 实现数据绑定我们需要创建一个User模型类public class User { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } }然后在代码中实现数据加载private void LoadUsers() { ListUser users new ListUser(); string sql SELECT Id, Name, Age FROM Users; using (SqlConnection conn new SqlConnection(connStr)) { conn.Open(); using (SqlCommand cmd new SqlCommand(sql, conn)) { using (SqlDataReader reader cmd.ExecuteReader()) { while (reader.Read()) { users.Add(new User { Id reader.GetInt32(0), Name reader.GetString(1), Age reader.GetInt32(2) }); } } } } usersGrid.ItemsSource users; }5. 项目优化与安全实践5.1 连接字符串加密把连接字符串写在代码中是非常危险的做法。正确的方式是使用配置文件在app.config中添加connectionStrings add nameMyDB connectionStringServer.;DatabaseTestDB;User IDappuser;Password123456; providerNameSystem.Data.SqlClient/ /connectionStrings在代码中读取string connStr ConfigurationManager.ConnectionStrings[MyDB].ConnectionString;5.2 使用异步方法长时间运行的数据库操作会阻塞UI线程应该使用异步版本的方法private async Task LoadUsersAsync() { // ... 省略其他代码 using (SqlConnection conn new SqlConnection(connStr)) { await conn.OpenAsync(); using (SqlCommand cmd new SqlCommand(sql, conn)) { using (SqlDataReader reader await cmd.ExecuteReaderAsync()) { // 处理数据 } } } }5.3 异常处理最佳实践完善的异常处理应该区分不同类型的错误try { // 数据库操作 } catch (SqlException ex) when (ex.Number 18456) { // 登录失败 } catch (SqlException ex) when (ex.Number 547) { // 外键约束冲突 } catch (SqlException ex) { // 其他SQL错误 } catch (Exception ex) { // 非数据库错误 }6. 完整项目源码解析现在让我们看一个完整的用户管理系统的实现。这个项目包含以下功能用户列表展示新增用户编辑用户信息删除用户按条件筛选用户核心代码结构/Models User.cs - 用户模型 /ViewModels UserViewModel.cs - 业务逻辑 /Views MainWindow.xaml - 主界面 App.config - 配置文件在UserViewModel中我们实现了所有数据库操作逻辑并通过属性与界面绑定。例如新增用户的方法public async Task AddUserAsync(User user) { string sql INSERT INTO Users (Name, Age) VALUES (Name, Age); SELECT SCOPE_IDENTITY();; using (var conn new SqlConnection(connStr)) { await conn.OpenAsync(); using (var cmd new SqlCommand(sql, conn)) { cmd.Parameters.AddWithValue(Name, user.Name); cmd.Parameters.AddWithValue(Age, user.Age); int newId Convert.ToInt32(await cmd.ExecuteScalarAsync()); user.Id newId; } } Users.Add(user); // 更新界面列表 }这个实现有几个亮点使用异步方法避免UI卡顿执行插入后立即获取自增ID自动更新绑定列表7. 常见问题排查在实际开发中你可能会遇到这些问题连接超时检查服务器地址是否正确检查网络是否通畅适当增加Connect Timeout的值登录失败确认用户名密码正确检查SQL Server是否允许混合验证模式确认sa账号是否启用查询结果为空检查查询条件是否正确先用Management Studio验证数据是否存在检查表名和列名是否拼写正确性能问题确保频繁使用的查询有适当的索引考虑使用存储过程代替复杂查询批量操作时使用事务我在项目中曾经遇到一个棘手的问题在虚拟机上运行的SQL Server经常断开连接。后来发现是虚拟机电源设置导致的网卡休眠修改电源选项后问题解决。这提醒我们数据库问题有时可能和环境和配置有关。