基于WCF的客户端-服务器聊天应用Npgsql连接未打开问题求助
WCF聊天应用PostgreSQL连接问题排查与解决
问题描述
开发基于WCF的客户端-服务器聊天应用,使用与其他项目相同的PostgreSQL连接代码,但注册功能无法正常运行,清理Npgsql连接池无效。
客户端代码
private void bReg_Click(object sender, RoutedEventArgs e) { client = new ServiceChatClient(new System.ServiceModel.InstanceContext(this)); string response = client.Registration(tbUserName.Text,tbPassword.Text); MessageBox.Show(response); string[] responseSub = response.Split('#'); if (responseSub[1] == string.Empty) { MessageBox.Show(responseSub[0]); } else { MessageBox.Show(responseSub[0]); } }
服务端ServiceChat代码
连接字符串与全局变量
string connstring = String.Format("Server={0};Port={1};" + "User ID = {2};Password={3};Database={4};", "localhost", "5432", "postgres", "mypass", "users"); public NpgsqlCommand cmd; public string sql = null;
注册方法
public string Registration(string username, string password) { try { NpgsqlConnection conn = new NpgsqlConnection(connstring); conn.Open(); sql = @"SELECT * FROM users where username = :username"; NpgsqlCommand cmd = new NpgsqlCommand(sql, conn); cmd.Parameters.AddWithValue(":username", username); int result = Convert.ToInt32(cmd.ExecuteScalar()); if (result == 0) { sql = ("INSERT INTO USERS (username,password) VALUES (:username,:password)"); cmd = new NpgsqlCommand(sql, conn); if (password.Length >= 4 && username.Length > 0 && password.Length <= 128 && username.Length <= 128 && !password.Contains(' ')) { cmd.Parameters.AddWithValue("username", username); cmd.Parameters.AddWithValue("password", GetMD5(password)); cmd.ExecuteNonQuery(); conn.Close(); return "Registration completed successfully#OK"; } else { conn.Close(); return "Invalid username or password#"; } } else { conn.Close(); return "A user with the same username already exists#"; } } catch (Exception ex) { string error = string.Format("Error:{0} что-то пошло не так#", ex); return error; } }
核心问题与修复方案
1. ExecuteScalar使用错误
原代码中SELECT * FROM users where username = :username配合ExecuteScalar(),当用户不存在时,ExecuteScalar()返回null,执行Convert.ToInt32(null)会直接抛出InvalidCastException,进入catch块。
修复:改为查询用户数量,确保返回数值类型:
sql = @"SELECT COUNT(*) FROM users where username = :username";
2. 数据库资源未正确释放
原代码手动调用conn.Close(),但如果中间抛出异常,连接可能无法关闭,导致连接池耗尽。应使用using语句自动释放连接和命令:
try { using (NpgsqlConnection conn = new NpgsqlConnection(connstring)) { conn.Open(); // 检查用户是否存在 using (NpgsqlCommand cmd = new NpgsqlCommand(@"SELECT COUNT(*) FROM users where username = :username", conn)) { cmd.Parameters.AddWithValue(":username", username); int result = Convert.ToInt32(cmd.ExecuteScalar()); if (result == 0) { // 插入新用户 using (NpgsqlCommand insertCmd = new NpgsqlCommand(@"INSERT INTO USERS (username,password) VALUES (:username,:password)", conn)) { if (password.Length >= 4 && username.Length > 0 && password.Length <= 128 && username.Length <= 128 && !password.Contains(' ')) { insertCmd.Parameters.AddWithValue(":username", username); insertCmd.Parameters.AddWithValue(":password", GetMD5(password)); insertCmd.ExecuteNonQuery(); return "Registration completed successfully#OK"; } else { return "Invalid username or password#"; } } } else { return "A user with the same username already exists#"; } } } } catch (Exception ex) { return $"Error:{ex.Message} что-то пошло не так#"; }
3. 参数命名不一致
插入语句中参数使用username,但SQL里是:username,虽然Npgsql支持自动映射,但统一参数格式避免潜在问题:
insertCmd.Parameters.AddWithValue(":username", username); insertCmd.Parameters.AddWithValue(":password", GetMD5(password));
4. 客户端Response处理风险
原代码直接Split('#')后访问responseSub[1],如果返回的字符串没有#(比如异常信息格式错误),会导致IndexOutOfRangeException。添加长度判断:
string[] responseSub = response.Split('#'); if (responseSub.Length >= 1) { MessageBox.Show(responseSub[0]); }
5. WCF异常传递配置(调试用)
默认WCF不会传递详细异常信息到客户端,调试时可修改服务端配置文件,开启异常细节:
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="true"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>
注意生产环境需关闭此配置,避免泄露敏感信息。
额外排查步骤
- 确认PostgreSQL服务正在运行,端口5432对外开放
- 验证连接字符串中的用户名、密码、数据库名是否正确
- 检查数据库表
users的结构是否包含username和password字段,且字段类型匹配 - 在服务端添加日志,记录SQL执行细节和异常信息,便于定位问题
内容的提问来源于stack exchange,提问作者TBO9I_47_XPOMOCOMA
相关产品推荐
相关产品推荐

