从存储过程调用多个存储过程 - 循环中的sql

时间:2015-09-14 20:13:23

标签: c# xml wcf stored-procedures sql-server-2012

我经常听到,虽然循环和游标一样糟糕,但我认为这不是真的。 从性能角度来看,从C#调用多个存储过程是否更好,或允许存储过程以循环方式解析XML数据和调用过程?是否有更好的方法在SQL中调用未知数量的存储过程而不是循环?

让我解释一下

我必须设计并实现供应商消息系统。有一家第三方公司将XML消息发送给收件人,该收件人来自发件人。我公司可能在任何时候都是发件人或收件人。

我想出了一个使用SQL while循环来运行存储过程的设计,但是我担心它在面对大量循环时可能表现不佳。

基本思路是: 发件人 - >第三方(消息系统) - >接收器

当我的公司是接收方时,我的问题可能会发生:

  1. 发件人向第三方公司发送消息
  2. 第三方公司向我的公司发送消息
  3. WCF服务收到第三方公司的请求
  4. 调用存储过程,传递要解析的消息的xml
  5. 此存储过程解析xml并在XML中查找消息
  6. while循环遍历每条消息并调用存储过程来更新信息,并传递消息实例的ID。
  7. 消息XML是这样的:

    <envelope>
        <to></to>
        <from></from>
        ...
        <messages>
           <message>
               <id></id>
               ...
               <params>
                   <param>
                       <Name></Name>
                       <Value></Value>
                   <param>
                   ...
               </params>
           </message>
           ...
        </messages>
    </envelope>
    

    我可以在每次XML传输中接收或发送一条或多条消息。可能会立即收到多条消息。处理发送和接收XML的第三方公司的要求是我们总是以成功或失败来回应。我们有一个60秒的超时窗口来响应。由于这些限制,我自然害怕我不能在时间限制内完成我需要做的所有处理,导致超时。

    因此,如果我在一次传输中找到消息1,2和3,我将必须运行存储过程1,2和3.我有一个临时表,其中包含消息ID和存储过程以运行。

    因此,While循环基本上是(没有检查这部分的有效性,只是随心所欲,因为我没有SP方便)

    While select count(*) from #temptable > 0
    begin
        select top 1 @idMessage = idMessage, @spToRun = spToRun from #temptable
        exec @spToRun @idMessage
    
        delete from #temptable where idMessage = @idMessage
        select @idMessage = null, @spToRun = null
    end
    

    我害怕把它投入生产,然后发现它运行得太远,太慢了。有没有人有建议?

2 个答案:

答案 0 :(得分:0)

我的建议是继续使用C#来解析xml并根据需要从dotnet端调用sprocs(只要你保持sql短而甜)。显然我并不完全熟悉你的情况,但从我的经验来看,它很难调试sql存储过程,特别是当它们在逻辑/处理方面很重,就好像你正在做的那样,即使你正在使用游标/循环。从c#这样的环境中控制更细粒度,您可以在执行处理时放置断点,在内存中监视变量的值(或者在xml节点中),并捕获更多种错误,这些错误在非常有用时非常有用。从第三方接收文件。另外,虽然你可能认为sql与dot net这样的中间件一样好,但它不是中间件,它通常最适合你的后端。通常在许多组织中,sql server在后端都有足够的功能,而且将来,如果你发现你已经过多地询问它并且它会开始对你表现得很奇怪,你可能会发现你的sql server负担过重。最后,就性能而言,我认为好处超过额外的行程时间,如果你保持sql简单并编译为存储过程,应该减轻,如果你把它放在生产服务器上,你应该有足够的内存。至少,如果我出于性能原因,我会偏向于C#/ dotnet,并依靠sql server做尽可能少的处理。

答案 1 :(得分:0)

最多1 MB的xml,我不会在存储过程中将其粉碎两次。 (你不会说xml中有多少行。)

您将获得比逐行发送更好的性能。

如果你有超过1 MB,请考虑使用goldie-locks方法。不要一个一个地发送它,不要发送它&#34;所有的东西&#34;,但是有一个外部的c#进程将xml分成更小的部分。例如:一个包含100,500行的文件,每次发送10,000封,发送11次。

您可以使用goldie-locks方法中的数字。

...

我会在C#中验证你的xml,然后我会把它发送到sql-server,就像我所说的那样#34; perfectXml&#34;,然后将它粉碎,也许变成#temp表,并从那里插入。再次,这是关键,xml应该是完美的&#34;从某种意义上说,你没有在tsql中运行检查以及if和this或那些语句。

按行划分Agonizing Row适用于鸟类。