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是开源的,我们可以自己部署! 本文和大家…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...

基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...

基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究
摘要:在消费市场竞争日益激烈的当下,传统体验营销方式存在诸多局限。本文聚焦开源AI智能名片链动2 1模式S2B2C商城小程序,探讨其在沉浸式体验营销中的应用。通过对比传统品鉴、工厂参观等初级体验方式,分析沉浸式体验的优势与价值…...