Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >使用相同的SqlCommand.BeginExecuteNonQuery对SqlConnection进行多次并发调用

使用相同的SqlCommand.BeginExecuteNonQuery对SqlConnection进行多次并发调用
EN

Stack Overflow用户
提问于 2011-06-16 08:01:04
回答 8查看 16.5K关注 0票数 30

我有一些工作的C#代码,这些代码使用SqlConnection创建临时表(例如#Foo),调用存储的procs来填充这些临时表并将结果返回给C#客户端,使用c#对这些结果执行复杂的计算,并使用计算结果更新前面创建的一个临时表。

由于整个过程中使用的临时表,我们必须只有一个SqlConnection。

在用计算结果更新临时表时,我发现了一个性能瓶颈。这段代码已经在批处理更新,以防止C#客户端耗尽内存。每一批计算数据都通过SqlCommand.ExecuteNonQuery发送到存储的proc,而sproc依次更新临时表。代码在调用ExecuteNonQuery时花费了大部分时间。

因此,我将其更改为BeginExecuteNonQuery,以及等待线程并调用EndExecuteNonQuery的代码。这提高了大约三分之一的性能,但我担心使用同一个SqlConnection对SqlCommand.BeginExecuteNonQuery进行多个并发调用。

这样可以吗,还是会遇到线程问题?

抱歉解释得太长了。

MSDN文档状态:

BeginExecuteNonQuery方法会立即返回,但是在代码执行相应的EndExecuteNonQuery方法调用之前,它不能对同一个SqlCommand对象执行任何启动同步或异步执行的其他调用。

这似乎意味着不同的SqlCommand对象可以在第一个SqlCommand完成之前调用BeginExecuteNonQuery。

下面是一些说明问题的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    private class SqlCommandData
    {
        public SqlCommand Command { get; set; }
        public IAsyncResult AsyncResult { get; set; }
    }

    public static void TestMultipleConcurrentBeginExecuteNonQueryCalls(string baseConnectionString)
    {
        var connectionStringBuilder = new SqlConnectionStringBuilder(baseConnectionString)
                                          {
                                              MultipleActiveResultSets = true,
                                              AsynchronousProcessing = true
                                          };
        using (var connection = new SqlConnection(connectionStringBuilder.ConnectionString))
        {
            connection.Open();

            // ELIDED - code that uses connection to do various Sql work

            SqlDataReader dataReader = null;
                // in real code, this would be initialized from calls to SqlCommand.ExecuteReader, using same connection

            var commandDatas = new List<SqlCommandData>();
            var count = 0;
            const int maxCountPerJob = 10000;
            while (dataReader.Read())
            {
                count++;
                // ELIDED - do some calculations on data, too complex to do in SQL stored proc
                if (count >= maxCountPerJob)
                {
                    count = 0;
                    var commandData = new SqlCommandData
                                          {
                                              Command = new SqlCommand {Connection = connection}
                                          };
                    // ELIDED - other initialization of command - used to send the results of calculation back to DB
                    commandData.AsyncResult = commandData.Command.BeginExecuteNonQuery();
                    commandDatas.Add(commandData);
                }
            }
            dataReader.Close();

            WaitHandle.WaitAll(commandDatas.Select(c => c.AsyncResult.AsyncWaitHandle).ToArray());
            foreach (var commandData in commandDatas)
            {
                commandData.Command.EndExecuteNonQuery(commandData.AsyncResult);
                commandData.Command.Dispose();
            }

            // ELIDED - more code using same SqlConnection to do final work

            connection.Close();
        }
    }
EN

回答 8

Stack Overflow用户

发布于 2011-07-07 14:40:46

嗯,尽管极有可能获得大量的选票,但我不得不对此发表评论。首先,这是一个很好的问题,很好地阐述了你提到的具体的潜在问题。然而,你忽略了讨论这个你想要完成的“漫长”过程。

我的经验让我想到一件事..。

如果你问的问题很难回答,就改变这个问题。

虽然我对你的具体问题知之甚少,但我认为这完全适用于你的困境。正如其他人提到的..。临时表令人讨厌,为特定任务创建自己的表更困难,在SQL中更新大量数据是很昂贵的。

问问自己:“你能避免这一切吗?”

人们常常选择在数据库中实现极其复杂的逻辑,因为他们相信SQL可以更快地实现它。实际上,这是一个有缺陷的概念,数据库是存储/序列化设备,它们擅长存储、更新、定位和同步访问数据。他们没有很好的设备来处理复杂的行动。即使在Microsoft(和其他人)通过向数据库中注入完整的开发语言来实现数据库的私生子化之后,它也不能像编写得很好的客户端那样最优地执行(*取决于操作的复杂性,我想您已经超过了这一点)。

例如,您有一个包含大约2gb的原始数据的数据库。您希望对整个数据集生成复杂的报告或分析。简单地说,2gb的内存是很容易获得的,使用字典或任何东西来创建您需要的查找,将整个数据库(或您需要的部分)读入内存。取决于几个因素,整个程序的运行速度可能比SQL快几倍,可以很容易地进行单元测试,并且(IMHO)比构建动态SQL的各种SPROCs更容易构建、调试和维护。即使有超过2gb的原始数据,客户端缓存也可以很容易地使用现有的几种技术(B树、ISAM等)创建。

我今天使用的产品在数据库中有2.4tb的数据,而且我们没有一个sproc、join语句,甚至没有一个不相等的where子句。

但遗憾的是,我的建议可能与你的具体情况相关,也可能与你的具体情况无关,因为我不知道你的目标或限制。希望,如果没有别的,它会让你问自己:

“我问的问题对吗?”

票数 17
EN

Stack Overflow用户

发布于 2011-06-28 12:39:44

您可以使用具有两个线程和两个同时但独立的sql连接的生产者-使用者模式。

生产者(第一个线程)具有DataReader (第一个sql连接),并将其结果写入阻塞队列。使用者(第二个线程)从队列中读取,具有ExecuteNonQuery (第二个sql连接)并写入临时表。

在ExecuteNonQuery命令基本上是多个插入的情况下,另一个想法是:ExecuteNonQuery具有带有StringCollection的重载作为一个操作发送多个sql语句。

票数 3
EN

Stack Overflow用户

发布于 2011-07-10 16:43:41

只能有一个与命令对象相关联的DataReader,也可以有多个与同一连接相关联的命令对象。这里唯一不能做的事情是使用具有不同参数的相同命令。

但是,当您启动数据库事务时(如果不是显式的话),与该事务关联的资源将被锁定,直到事务被提交或回滚,并且所有希望查询这些资源的进程都被放入队列中。Server很好地管理队列。由于SQL server 2000中服务器负载高,我在死锁方面遇到了一些问题,但是在以后的版本中没有出现这样的问题。

奇怪的是,您实际上得到了性能改进。这使我认为您有大量的数据,在发送到Server时需要时间进行处理。在发送块时,由于同时执行数据传输和数据处理,因此消耗的时间较少。

不管怎样,这不应该有任何问题。

但是,考虑使用CLR程序集(如果有此选项)直接在数据库引擎中处理信息,而不需要TCP通信量。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6374911

复制
相关文章
Python抛出异常_python抛出异常的作用
在python中不同的异常可以用不同的类型(python中统一了类与类型,类型即类)去标识,不同的类对象标识不同的异常,一个异常标识一种错误
全栈程序员站长
2022/11/02
2.5K0
Java陷阱之:finally块抛出异常或return导致异常丢失
java中finally语句包含有抛出异常或者return语句,会把try块中出现的异常丢弃。
崔认知
2023/06/19
8830
Java陷阱之:finally块抛出异常或return导致异常丢失
【C++ 语言】异常 ( 抛出字符串异常 | 抛出异常对象 | 抛出任意对象 | 抛出自定义异常 )
1. 异常处理 : 使用 " try{}catch(){} " 将抛出异常的代码包起来 , 注意将可能抛出异常的代码包裹在 try 后的大括号中 , 将异常处理逻辑放在 catch 后的大括号中 ;
韩曙亮
2023/03/27
1.3K0
django 获取字段选项 choice 的值
由二项元组构成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,而且这个选择框的选项就是choices 中的选项。
卓越笔记
2023/02/18
2.7K0
android 抛出FileNotFoundException异常
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
全栈程序员站长
2022/11/17
1.6K0
.net remoting 抛出异常
所有在远程软件运行的类,如果需要传输到本地,都需要继承 MarshalByRefObject 或其他可以序列化的类。
林德熙
2018/09/19
1.5K0
.net remoting 抛出异常
dotnet remoting 抛出异常
所有在远程软件运行的类,如果需要传输到本地,都需要继承 MarshalByRefObject 或其他可以序列化的类。
林德熙
2019/09/27
1.4K0
dotnet remoting 抛出异常
python抛出异常和捕获异常_在try块中可以抛出异常吗
2.解析 关键字try 以及except是 使用Python 解释器主动抛出异常的关键, Python解释器从上向下执行 当运行try中的某行代码出错,会直接进入except中执行下方代码 try中错行下方的代码不会被运行 except…as… 是固定的语法格式 打印traceback信息 finally 后的代码不管是否抛出异常都会执行 except 的原理 调用sys中 exc.info 方法返回基本信息 所以抛出异常的第一步拓展可以在这里开始 注意 每个关键字下方的代码都是独立的(所有的变量都是局部变量)
全栈程序员站长
2022/11/02
4.5K0
python抛出异常会终止程序吗_catch里面抛出异常
如果没有 try 和 except 语句覆盖抛出异常的 raise 语句,该程序就会崩溃,并显示异常的出错信息。通常是调用该函数的代码知道如何处理异常,而不是该函数本身。所以你常常会看到 raise 语句在一个函数中,try 和 except 语句在调用该函数的代码中。
全栈程序员站长
2022/11/19
2.2K0
dotnet remoting 抛出异常
所有在远程软件运行的类,如果需要传输到本地,都需要继承 MarshalByRefObject 或其他可以序列化的类。
林德熙
2022/08/04
1K0
python抛出异常和捕获异常_Python异常
class Widget: def __init__(self,size=(40,40)): self._size=size def getSize(self): return self._size def resize(self,width,height): if width<0 or height<0:
全栈程序员站长
2022/11/02
2.9K0
应该抛出什么异常?不应该抛出什么异常?(.NET/C#)
2018-02-04 13:25
walterlv
2018/09/18
1.7K0
python抛出异常会终止程序吗_python抛出异常的作用
当python执行无效的代码时,就会抛出异常。用 try 和 catch 语句可以处理异常,以避免程序的崩溃。我们也可以在代码中抛出自己的异常,抛出异常意味着 停止运行这个函数中的代码,将程序执行转到except语句
全栈程序员站长
2022/11/02
1.8K0
c++构造函数是否可以抛出异常_什么叫抛出异常
从语法上来说,构造函数可以抛出异常。但从逻辑上和风险控制上,构造函数中尽量不要抛出异常。万不得已,一定要注意防止内存泄露。
全栈程序员站长
2022/09/22
1.7K1
Java 捕获和抛出异常
Java中把非正常情况分为两种:异常(Exception)和错误(Error),其中Error错误一般是指与虚拟机相关的问题,这种错误无法恢复或不可能捕获,而对于Exception异常我们可以使用try…catch进行捕获。try…catch不允许存在单独的try块或catch块,可存在多个catch块。try块中存放业务功能代码,catch块中存放异常处理代码。Java7后支持用catch捕获多个异常,也可捕获自定义异常。对于捕获的异常一般可以使用printStackTrace()方法追踪输出至标准错误流。try…catch后可以添加finally,使用finally可以保证除系统退出外finally块中代码绝对执行。捕获异常时需要注意一定要先捕获小异常,再捕获大异常,否则小异常将无法被捕获。代码示例如下
用户7886150
2021/04/06
1.9K0
django 主动抛出 403 异常
* 网站名称:obaby@mars * 网址:https://h4ck.org.cn/ * 本文标题: 《django 主动抛出 403 异常》 * 本文链接:https://h4ck.org.cn/2018/12/django-%e4%b8%bb%e5%8a%a8%e6%8a%9b%e5%87%ba-403-%e5%bc%82%e5%b8%b8/ * 转载文章请标明文章来源,原文标题以及原文链接。请遵从 《署名-非商业性使用-相同方式共享 2.5 中国大陆 (CC BY-NC-SA 2.5 CN) 》许可协议。
obaby
2023/02/24
7540
python中用来抛出异常的关键字是( )_python异常抛出
动抛出异常raise typeerror(类型错误) # 7. 触发异常try: raise typeerror(类型错误)except exception as e: print(e) # 8. 自定义异常class my…syntaxerror 语法错误 python代码非法,代码不能编译(个人认为这是语法错误,写错了) typeerror 类型错误传入对象类型与要求的不符合 unboundlocalerror …
全栈程序员站长
2022/11/02
1K0
interrupt+抛出异常测试
建议使用“抛异常”的方法来实现线程的停止,因为在catch块中可以对异常的信息进行相关的处理,而且使用异常流能更好、更方便的控制程序的运行流程,不至于代码中出现很多个return;污染代码。
用户7365393
2021/10/07
4980
在python中,如果异常并未被处理或捕捉_抛出异常是什么意思
Python使用异常类来管理异常信息。当发生异常的时候,程序会抛出一个异常信息,自动根据代码的层次查找异常处理信息。当代码发生异常而没有指定处理异常的方法是,Traceback会打印发生异常时代码执行栈的情况。
全栈程序员站长
2022/11/02
1.6K0
Java 如何抛出异常、自定义异常
1、定义 : 一个方法不处理这个异常,而是调用层次向上传递,谁调用这个方法,这个异常就由谁来处理。
Java编程指南
2019/08/02
4.8K0
Java 如何抛出异常、自定义异常

相似问题

按值或引用抛出异常

23

抛出异常或返回值

45

抛出异常或返回值

11

抛出异常,然后传播或返回布尔值,然后抛出异常?

11

为"Find“方法抛出异常或返回选项更好吗?

20
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文