如何避免C#中数据库操作时重复编写相同的try/catch代码块?
消除重复SQL操作代码的方案
完全可以通过Func<T>和Action封装通用逻辑,既避免重复的try/catch和using块,又能保证数据库连接被正确关闭——using语句的资源清理机制不受封装影响,无论代码正常执行还是抛出异常,都会自动调用Dispose()释放连接。
1. 无返回值的SQL操作封装
如果你的操作不需要返回结果,封装一个接受Action<SqlConnection>的通用方法:
private void ExecuteSql(Action<SqlConnection> sqlAction) { using (var connection = GetAndOpenSQLConnection()) { try { sqlAction(connection); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } }
使用示例:
ExecuteSql(conn => { // 编写具体SQL操作,比如执行无返回的存储过程 var cmd = new SqlCommand("InsertDataProc", conn); cmd.Parameters.AddWithValue("@Param", "Value"); cmd.ExecuteNonQuery(); });
2. 有返回值的SQL操作封装
如果需要返回数据(比如查询结果),使用Func<SqlConnection, T>来封装:
private T ExecuteSql<T>(Func<SqlConnection, T> sqlFunc) { using (var connection = GetAndOpenSQLConnection()) { try { return sqlFunc(connection); } catch (Exception ex) { MessageBox.Show(ex.ToString()); return default(T); // 引用类型会返回null,值类型返回默认值 } } }
使用示例(返回DataTable):
var dataTable = ExecuteSql<DataTable>(conn => { var cmd = new SqlCommand("QueryDataProc", conn); var adapter = new SqlDataAdapter(cmd); var dt = new DataTable(); adapter.Fill(dt); return dt; });
关键说明
using块的可靠性不受影响:编译器会自动把using的逻辑转换为包含finally的代码块,无论委托内代码执行情况如何,连接都会被释放。- 可扩展异常处理:如果需要针对特定异常(如
SqlException)做特殊处理,可在通用方法的catch块中添加类型判断,其他异常可选择重新抛出。 - 进一步优化:还可以把创建
SqlCommand、添加参数等重复步骤也封装进通用方法,进一步减少冗余代码。
内容的提问来源于stack exchange,提问作者J. Mini
相关产品推荐
相关产品推荐

