C#程序调用Sql Server存储过程异常处理:调用存储过程后不返回、不抛异常的解决方案
目录
一、代码解析:
二、解决方案
1、增加日志记录
2、异步操作
注意事项
3、增加超时机制
4、使用线程池
5、使用信号量或事件
6、监控数据库连接状态
在C#程序操作Sql Server数据库的实际应用中,若异常就会抛出异常,我们还能找到异常的原因,进一步去解决;但偶发的不返回、也不抛出异常的情况真是令人头疼,下面我将从C#程序代码层面去分析解决思路,先上代码
/// <summary>/// 执行存储过程,返回影响的行数/// </summary>/// <param name="procedureName">存储过程名</param>/// <param name="parameters">自定义参数数组,根据调用数据库的种类,给参数中相应的数组赋值</param>/// <returns></returns>public int ExecuteProcedure(string procedureName, object[] aParas){SqlCommand cmd = new SqlCommand();try{PrepareCommand(con, cmd, null, CommandType.StoredProcedure, procedureName, aParas);int rows = cmd.ExecuteNonQuery();cmd.Parameters.Clear();return rows;}catch (Exception err){throw err;}}
一、代码解析:
我们解析下这个函数,这个也是一个比较简单常用的方法:
这个函数的作用是执行一个存储过程,并返回该存储过程执行后影响的行数。下面是对函数各个部分的详细解释:
函数定义
/// <summary>
/// 执行存储过程,返回影响的行数
/// </summary>
/// <param name="procedureName">存储过程名</param>
/// <param name="parameters">自定义参数数组,根据调用数据库的种类,给参数中相应的数组赋值</param>
/// <returns></returns>
public int ExecuteProcedure(string procedureName, object[] aParas)
- summary: 该函数用于执行存储过程并返回影响的行数。
- param:
procedureName是存储过程的名称。 - param:
parameters是一个自定义参数数组,根据调用数据库的种类,给参数中相应的数组赋值。 - returns: 返回存储过程执行后影响的行数。
函数实现
public int ExecuteProcedure(string procedureName, object[] aParas)
{//创建SqlCommand对象SqlCommand cmd = new SqlCommand();try{//调用PrepareCommand方法来设置SqlCommand对象的参数,包括连接对象con、命令对象cmd、命令类型(这里是存储过程)、存储过程名称和参数数组。PrepareCommand(con, cmd, null, CommandType.StoredProcedure, procedureName, aParas);//使用ExecuteNonQuery方法执行存储过程,并返回影响的行数。int rows = cmd.ExecuteNonQuery();//清除SqlCommand对象的参数,以便下次使用。cmd.Parameters.Clear();return rows;}catch (Exception err){//捕获并抛出任何可能发生的异常。throw err;}
}
这个函数的主要作用是执行一个存储过程,并返回该存储过程执行后影响的行数。它通过设置SqlCommand对象的参数,执行存储过程,并处理可能发生的异常。
二、解决方案
问题:在实际应用中遇到这种情况,即在调用 ExecuteProcedure 方法后,没有到达 return rows; 语句,也没有进入 catch (Exception err) 块,这意味着代码在某个地方被阻塞或挂起,但没有抛出异常。这可能是由于以下几种情况之一:
-
死锁或资源争用:
- 数据库连接可能被其他操作占用,导致当前操作无法继续执行。
- 数据库中的某个存储过程可能存在死锁,导致执行被阻塞。
-
无限循环或长时间运行的操作:
- 存储过程中可能存在无限循环或长时间运行的操作,导致执行时间过长。
-
网络问题:
- 数据库服务器或网络连接可能出现问题,导致请求无法完成。
-
线程问题:
- 当前线程可能被其他线程或操作阻塞,导致无法继续执行。
-
内存或资源耗尽:
- 系统内存或资源可能耗尽,导致无法继续执行。
解决方法
-
增加日志记录:
- 在关键步骤增加更多的日志记录,以便更好地了解代码执行到哪个步骤。
-
检查数据库状态:
- 检查数据库服务器的状态,查看是否有死锁或其他问题。
- 使用数据库管理工具监控数据库性能和资源使用情况。
-
优化存储过程:
- 检查存储过程的逻辑,确保没有无限循环或长时间运行的操作。
- 优化存储过程的性能,减少资源消耗。
-
检查网络连接:
- 确保数据库服务器和应用程序之间的网络连接稳定。
-
监控系统资源:
- 监控系统内存、CPU 和其他资源的使用情况,确保没有资源耗尽的情况。
-
使用异步操作:
- 考虑将数据库操作改为异步操作,以避免阻塞主线程。
因为问题是偶发的,半年一年出现一次,也找不出什么原因,但是客户会较真,拿这个说事;以上方法,从代码层面只有1、6适用 ,当然我们也可以通过控制超时 时间来处理,实用解决方案如下:
1、增加日志记录
关键步骤增加日志记录,以便更好地了解代码执行情况:
public int ExecuteProcedure(string procedureName, object[] aParas)
{SqlCommand cmd = new SqlCommand();try{// 增加日志记录Log("Preparing command for procedure: " + procedureName);PrepareCommand(con, cmd, null, CommandType.StoredProcedure, procedureName, aParas);// 增加日志记录Log("Executing command for procedure: " + procedureName);int rows = cmd.ExecuteNonQuery();// 增加日志记录Log("Command executed successfully, rows affected: " + rows);cmd.Parameters.Clear();return rows;}catch (Exception err){// 增加日志记录Log("Exception occurred: " + err.Message);throw err;}
}private void Log(string message)
{// 实现日志记录逻辑,例如写入文件或数据库Console.WriteLine(message);
}
通过增加日志记录,可以更好地了解代码执行到哪个步骤,从而更容易定位问题,这种特殊情况也只能定位到走哪一行就没往下走了。
2、异步操作
将数据库操作改为异步操作可以提高应用程序的响应性和性能,特别是在处理大量数据或长时间运行的操作时。
使用 ExecuteNonQueryAsync 方法
SqlCommand 类提供了 ExecuteNonQueryAsync 方法,用于异步执行 SQL 命令。以下是修改后的 ExecuteProcedure 方法:
using System.Data;
using System.Data.SqlClient;
using System.Threading.Tasks;public async Task<int> ExecuteProcedureAsync(string procedureName, object[] aParas)
{SqlCommand cmd = new SqlCommand();try{// 增加日志记录Log("Preparing command for procedure: " + procedureName);PrepareCommand(con, cmd, null, CommandType.StoredProcedure, procedureName, aParas);// 异步执行命令Log("Executing command for procedure: " + procedureName);int rows = await cmd.ExecuteNonQueryAsync();// 增加日志记录Log("Command executed successfully, rows affected: " + rows);cmd.Parameters.Clear();return rows;}catch (Exception err){// 增加日志记录Log("Exception occurred: " + err.Message);throw err;}
}private void Log(string message)
{// 实现日志记录逻辑,例如写入文件或数据库Console.WriteLine(message);
}
调用异步方法
在调用异步方法时,需要使用 await 关键字,并且调用方法也必须是异步的。例如:
public async Task SomeMethodAsync()
{string procedureName = "YourStoredProcedureName";object[] parameters = new object[] { /* 参数值 */ };try{int rowsAffected = await ExecuteProcedureAsync(procedureName, parameters);Console.WriteLine("Rows affected: " + rowsAffected);}catch (Exception ex){Console.WriteLine("Exception: " + ex.Message);}
}
注意事项
- 异步方法的返回类型:异步方法的返回类型通常是
Task或Task<T>,其中T是方法的返回类型。 - 异步上下文:确保在异步上下文中调用异步方法,例如在
async方法中使用await。 - 异常处理:异步方法中的异常处理与同步方法类似,但需要使用
await关键字捕获异常。
通过将数据库操作改为异步操作,可以提高应用程序的性能和响应性,特别是在处理大量数据或长时间运行的操作时。
?????但是并不是所有程序都适合异步操作,那么将如何处理呢?
如果程序逻辑不能使用异步方式,但仍然遇到在调用 ExecuteProcedure 方法后没有到达 return rows; 语句的问题,可以考虑以下几种方法来解决这个问题:
3、增加超时机制
为数据库操作增加超时机制,确保操作不会无限期地阻塞。可以使用 SqlCommand 的 CommandTimeout 属性来设置超时时间。
public int ExecuteProcedure(string procedureName, object[] aParas)
{SqlCommand cmd = new SqlCommand();try{// 设置命令超时时间为30秒cmd.CommandTimeout = 30;PrepareCommand(con, cmd, null, CommandType.StoredProcedure, procedureName, aParas);int rows = cmd.ExecuteNonQuery();cmd.Parameters.Clear();return rows;}catch (Exception err){throw err;}
}
这个超时机制在特殊情况下没有用,亲测没用,就算不设置CommandTimeout属性的值,也有默认的吧,特殊情况等多久都没返回没异常。
4、使用线程池
将数据库操作放在单独的线程中执行,并在主线程中等待结果。可以使用 ThreadPool 或 Task 来实现这一点。
using System.Threading;public int ExecuteProcedure(string procedureName, object[] aParas)
{int rows = 0;bool isCompleted = false;Exception exception = null;ThreadPool.QueueUserWorkItem(_ =>{SqlCommand cmd = new SqlCommand();try{PrepareCommand(con, cmd, null, CommandType.StoredProcedure, procedureName, aParas);rows = cmd.ExecuteNonQuery();cmd.Parameters.Clear();}catch (Exception err){exception = err;}finally{isCompleted = true;}});// 等待操作完成或超时DateTime startTime = DateTime.Now;while (!isCompleted && (DateTime.Now - startTime).TotalSeconds < 30){Thread.Sleep(100);}if (exception != null){throw exception;}if (!isCompleted){throw new TimeoutException("Database operation timed out.");}return rows;
}
5、使用信号量或事件
使用信号量或事件来同步主线程和数据库操作线程。
using System.Threading;public int ExecuteProcedure(string procedureName, object[] aParas)
{int rows = 0;Exception exception = null;ManualResetEvent completionEvent = new ManualResetEvent(false);ThreadPool.QueueUserWorkItem(_ =>{SqlCommand cmd = new SqlCommand();try{PrepareCommand(con, cmd, null, CommandType.StoredProcedure, procedureName, aParas);rows = cmd.ExecuteNonQuery();cmd.Parameters.Clear();}catch (Exception err){exception = err;}finally{completionEvent.Set();}});// 等待操作完成或超时if (!completionEvent.WaitOne(TimeSpan.FromSeconds(30))){throw new TimeoutException("Database operation timed out.");}if (exception != null){throw exception;}return rows;
}
6、监控数据库连接状态
在执行数据库操作之前,检查数据库连接的状态,确保连接是可用的。
public int ExecuteProcedure(string procedureName, object[] aParas)
{SqlCommand cmd = new SqlCommand();try{// 检查数据库连接状态if (con.State != ConnectionState.Open){con.Open();}PrepareCommand(con, cmd, null, CommandType.StoredProcedure, procedureName, aParas);int rows = cmd.ExecuteNonQuery();cmd.Parameters.Clear();return rows;}catch (Exception err){throw err;}
}
通过以上方法,可以在不改变程序逻辑的情况下,增加超时机制、使用线程池、信号量或事件来解决数据库操作阻塞的问题。这些方法可以帮助确保数据库操作在合理的时间内完成,并在出现异常时及时处理。
相关文章:
C#程序调用Sql Server存储过程异常处理:调用存储过程后不返回、不抛异常的解决方案
目录 一、代码解析: 二、解决方案 1、增加日志记录 2、异步操作 注意事项 3、增加超时机制 4、使用线程池 5、使用信号量或事件 6、监控数据库连接状态 在C#程序操作Sql Server数据库的实际应用中,若异常就会抛出异常,我们还能找到异…...
数据统计与数据分组18-25题(30 天 Pandas 挑战)
数据统计与数据分组 1. 知识点1.18 分箱与统计个数1.19 分组与求和统计1.20 分组获取最小值1.21 分组获取值个数1.22 分组与条件查询1.23 分组与条件查询及获取最大值1.24 分组及自定义函数1.25 分组lambda函数统计 2. 题目2.18 按分类统计薪水(数据统计)…...
Apache Seata应用侧启动过程剖析——注册中心与配置中心模块
本文来自 Apache Seata官方文档,欢迎访问官网,查看更多深度文章。 本文来自 Apache Seata官方文档,欢迎访问官网,查看更多深度文章。 Apache Seata应用侧启动过程剖析——注册中心与配置中心模块 前言 在Seata的应用侧…...
大话光学原理:1.“实体泛光说”、反射与折射
一、实体泛光说 在古希腊,那些喜好沉思的智者们中,曾流传着一个奇妙的设想:他们认为,我们的眼睛仿佛伸出无数触手般的光线,这些光线能向四面八方延伸,紧紧抓住周围的每一个物体。于是,当我们凝视…...
住宅代理、移动代理和数据中心代理之间的区别
如果您是一名认真的互联网用户,可能需要反复访问某个网站或服务器,可能是为了数据抓取、价格比较、SEO 监控等用例,而不会被 IP 列入黑名单或被 CAPTCHA 阻止。 代理的工作原理是将所有传出数据发送到代理服务器,然后代理服务器将…...
光学传感器图像处理流程(一)
光学传感器图像处理流程(一) 1. 处理流程总览2. 详细处理流程2.1. 图像预处理2.1.1. 降噪处理2.1.2. 薄云处理2.1.3. 阴影处理 2.2. 辐射校正2.2.1. 辐射定标2.2.2. 大气校正2.2.3. 地形校正 2.3. 几何校正2.3.1. 图像配准2.3.2. 几何粗校正2.3.3. 几何精…...
el-table 树状表格查询符合条件的数据
需要对el-table的树状表格根据输入机构名称,筛选出符合条件的数据,可用如下方法: 页面内容如下: <el-input v-model"ogeName" placeholder"请输入机构名称"><el-table :data"list" row…...
MQTT教程--服务器使用EMQX和客户端使用MQTTX
什么是MQTT MQTT(Message Queuing Telemetry Transport)是一种轻量级、基于发布-订阅模式的消息传输协议,适用于资源受限的设备和低带宽、高延迟或不稳定的网络环境。它在物联网应用中广受欢迎,能够实现传感器、执行器和其它设备…...
326. 3 的幂
哈喽!大家好,我是奇哥,一位专门给面试官添堵的职业面试员 文章持续更新,可以微信搜索【小奇JAVA面试】第一时间阅读,回复【资料】更有我为大家准备的福利哟! 文章目录 一、题目二、答案三、总结 一、题目 …...
多标签问题
一、多标签问题与单标签问题的区别: 多标签问题是单标签问题的推广。 举个例子,同时识别图片中的小汽车,公交车,行人时,标签值有三个:小汽车,公交车,行人。 单标签问题仅对一个标签…...
suricata7 rule加载(三)加载options
suricata7.0.5 加载options (msg:“HTTP Request Example”; flow:established,to_server; http.method; content:“POST”; http.uri; content:“query.php”; bsize:>9; http.protocol; content:“HTTP/1.1”; bsize:8; http.host; content:“360”; bsize:>3; class…...
【电路笔记】-C类放大器
C类放大器 文章目录 C类放大器1、概述2、C类放大介绍3、C类放大器的功能4、C 类放大器的效率5、C类放大器的应用:倍频器6、总结1、概述 尽管存在差异,但我们在之前有关 A 类、B 类和 AB 类放大器的文章中已经看到,这三类放大器是线性或部分线性的,因为它们在放大过程中再现…...
c++语法之函数重载
引例 我们在C语言里面写add函数的时候,只能支持一种类型的相加,除非我们创建多个add函数: 但是这样写并不方便,于是就有了c的函数重载。 函数重载 函数重载就是可以将多个参数类型、顺序、数量不同,实现逻辑相同的函…...
EtherCAT主站IGH-- 11 -- IGH之fmmu_config.h/c文件解析
EtherCAT主站IGH-- 11 -- IGH之fmmu_config.h/c文件解析 0 预览一 该文件功能`fmmu_config.c` 文件功能函数预览二 函数功能介绍1. `ec_fmmu_config_init`2. `ec_fmmu_set_domain_offset_size`3. `ec_fmmu_config_page`示例用法示例详细说明三 h文件翻译四 c文件翻译该文档修改…...
如何使用IDEA快速清理无效代码(荣耀典藏版)
大家好,我是月夜枫。 今天分享一下IDEA中很有实用价值的Analyze,那么Analyze是用来做什么的呢? 主要用来清理没有引用的代码,包括方法、实体类以及没有使用的Mapper和Service等。 为了是项目更加整洁,可以使用Idea中…...
ELK优化之Filebeat部署
目录 1.安装配置Nginx 2.安装 Filebeat 3.设置 filebeat 的主配置文件 4.修改Logstash配置 5.启动配置 6.kibana验证 主机名ip地址主要软件es01192.168.9.114ElasticSearches02192.168.9.115ElasticSearches03192.168.9.116ElasticSearch、Kibananginx01192.168.9.113ng…...
蝙蝠优化算法(Bat Algorithm,BA)及其Python和MATLAB实现
蝙蝠优化算法(Bat Algorithm,简称BA)是一种基于蝙蝠群体行为的启发式优化算法,由Xin-She Yang于2010年提出。该算法模拟了蝙蝠捕食时在探测目标、适应环境和调整自身位置等过程中的行为,通过改进搜索过程来实现优化问题…...
vscode运行java中文乱码,引发的mac配置问题
文章目录 问题 vscode 安装 java环境之后 public class Main{ public static void main(String[] args) { System.out.println(“哈哈”); } } ➜ .leetcode cd “/Users/leesin/.leetcode/.vscode/” && javac -encoding utf-8 Main.java && java Main &am…...
MySQL之备份与恢复(五)
备份与恢复 备份数据 符号分隔文件备份 可以使用SQL命令SELECT INTO OUTFILE以符号分隔文件格式创建数据的逻辑备份。(可以用mysqldump的 --tab选项导出到符号分隔文件中)。符号分隔文件包含以ASCII展示的原始数据,没有SQL、注释和列名。下面是一个导出为逗号分隔…...
离线运行Llama3:本地部署终极指南_liama2 本地部署
4月18日,Meta在官方博客官宣了Llama3,标志着人工智能领域迈向了一个重要的飞跃。经过笔者的个人体验,Llama3 8B效果已经超越GPT-3.5,最为重要的是,Llama3是开源的,我们可以自己部署! 本文和大家…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用
文章目录 一、背景知识:什么是 B-Tree 和 BTree? B-Tree(平衡多路查找树) BTree(B-Tree 的变种) 二、结构对比:一张图看懂 三、为什么 MySQL InnoDB 选择 BTree? 1. 范围查询更快 2…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
