C# SSIS脚本转换-执行WebClient异步操作

C# SSIS脚本转换-执行WebClient异步操作,c#,sql,sql-server,ssis,C#,Sql,Sql Server,Ssis,我收到6个不同域/主机的唯一URL,解析它们返回的XML,并插入到表中。除了同步地(一次一台)运行每台服务器之外,我还可以很好地工作。我需要它同时联系所有六台服务器 我将WebClient调用更改为使用Async方法,然后添加了一个while语句来检查是否所有WebClient调用都已返回,但是在while语句完成后,SSIS包似乎被取消,无论我是否有对SetEndOfRowSet的调用。SSIS日志记录中未显示任何错误(即使选择了所有日志选项)。它在输出窗口中显示“取消”,并且有一个简短的控制

我收到6个不同域/主机的唯一URL,解析它们返回的XML,并插入到表中。除了同步地(一次一台)运行每台服务器之外,我还可以很好地工作。我需要它同时联系所有六台服务器

我将WebClient调用更改为使用Async方法,然后添加了一个while语句来检查是否所有WebClient调用都已返回,但是在while语句完成后,SSIS包似乎被取消,无论我是否有对SetEndOfRowSet的调用。SSIS日志记录中未显示任何错误(即使选择了所有日志选项)。它在输出窗口中显示“取消”,并且有一个简短的控制台窗口,当它发生时会弹出,但我无法捕捉它

如果SSIS包中没有while语句,那么包将继续经过脚本转换,并且不会从中输出任何行。SynchronousInputID上的脚本转换设置为“无”

以下是SSIS C#脚本转换代码:

/* Microsoft SQL Server Integration Services Script Component
*  Write scripts using Microsoft Visual C# 2008.
*  ScriptMain is the entry point class of the script.*/

using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using System.Net;
using System.Diagnostics;
using System.Xml;

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent

{
    private int CountComplete = 0;

public override void PreExecute()
{
    base.PreExecute();
}

public override void PostExecute()
{
    base.PostExecute();
}

public override void Input0_ProcessInput(Input0Buffer Buffer)
{
    while(Buffer.NextRow())
    {
        Input0_ProcessInputRow(Buffer);
    }

    if (Buffer.EndOfRowset())
    {
        while (CountComplete < Variables.intRows)
        {
            System.Threading.Thread.Sleep(500);
        }
        Output0Buffer.SetEndOfRowset();
    }
}

public override void Input0_ProcessInputRow(Input0Buffer Row)
{
    string DNS_NA = Row.DNSNA;
    long SERVER = Convert.ToInt64(Row.SERSYSNR);

    // Ignore server/certificate mismatch...
    ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;

    // Declare variable that will hold the xml document received by the API
    string xmlDoc = String.Empty;

    // Get the URI from the variable
    string url = @"https://" + DNS_NA + Variables.strURLSuffix;

    // Time the request...
    Stopwatch timer = Stopwatch.StartNew();
    //Create a Web Client
    WebClient client = new WebClient();
    client.DownloadStringCompleted += (sender, e) =>
    {
        timer.Stop();
        processRow(e.Result, SERVER, Convert.ToInt32(timer.ElapsedMilliseconds), Convert.ToInt32(Row.UPTIMQY), Output0Buffer);
        CountComplete += 1;
    };
    Uri uri = new Uri(url);
    client.DownloadStringAsync(uri);
}

private void processRow(string xmlDoc, long SERVER, int FRAPI_TIME, int PRE_UPTIME, Output0Buffer buffer)
{
    try
    {
        XmlDocument xDoc = new XmlDocument();

        xDoc.LoadXml(xmlDoc);

        bool NORESPONSE = false; // If we made it this far, we got a response, right?
        short CPU = Convert.ToInt16(xDoc.SelectSingleNode("//server").ChildNodes[1].InnerText);
        int TOT_MEM = Convert.ToInt32(xDoc.SelectSingleNode("//server").ChildNodes[2].InnerText) / (1024 * 1024);
        int USE_MEM = Convert.ToInt32(xDoc.SelectSingleNode("//server").ChildNodes[3].InnerText) / (1024 * 1024);
        int UPTIME = Convert.ToInt32(xDoc.SelectSingleNode("//server").ChildNodes[4].InnerText) / 1000 / 60;
        short REQUESTS = Convert.ToInt16(xDoc.SelectSingleNode("//server").ChildNodes[5].InnerText);
        bool RESET = (UPTIME < PRE_UPTIME) ? true : false;


        foreach (XmlNode xNode in xDoc.SelectNodes("//server/detail/request"))
        {
            buffer.AddRow();
            buffer.SERSYSNR = SERVER;
            buffer.CPUUSEQY = CPU;
            buffer.TOTMEMQY = TOT_MEM;
            buffer.USEMEMQY = USE_MEM;
            buffer.UPTIMQY = UPTIME;
            buffer.REQCNTQY = REQUESTS;
            buffer.REQMSQY = FRAPI_TIME;
            buffer.SERNONRSPIR = NORESPONSE;
            buffer.SERRSTIR = RESET;
            buffer.REQSYSNR = Convert.ToInt32(xNode.ChildNodes[0].InnerText);
            buffer.REQIPTE = xNode.ChildNodes[1].InnerText;
            buffer.REQURLTE = xNode.ChildNodes[2].InnerText;
            buffer.REQRUNTMQY = Convert.ToInt32(xNode.ChildNodes[3].InnerText);

        }
    }
    catch
    {
        // Hopefully we didn't throw an exception inside the foreach where a row has already been added...
        buffer.AddRow();
        buffer.SERSYSNR = SERVER;
        buffer.SERNONRSPIR = true;
    }

}

   // public override void CreateNewOutputRows()
   // {
        /*
          Add rows by calling the AddRow method on the member variable named "<Output Name>Buffer".
          For example, call MyOutputBuffer.AddRow() if your output was named "MyOutput".
        */
    //}

}
/*Microsoft SQL Server集成服务脚本组件
*使用Microsoft Visual C#2008编写脚本。
*ScriptMain是脚本的入口点类*/
使用制度;
使用系统数据;
使用Microsoft.SqlServer.Dts.Pipeline.Wrapper;
使用Microsoft.SqlServer.Dts.Runtime.Wrapper;
Net系统;
使用系统诊断;
使用System.Xml;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
公共类ScriptMain:UserComponent
{
私有整数CountComplete=0;
公共覆盖无效预执行()
{
base.PreExecute();
}
公共重写void PostExecute()
{
base.PostExecute();
}
公共覆盖无效Input0\u ProcessInput(Input0Buffer)
{
while(Buffer.NextRow())
{
Input0\u进程inputRow(缓冲区);
}
if(Buffer.EndOfRowset())
{
while(CountCompletetrue;
//声明将保存API接收的xml文档的变量
string xmlDoc=string.Empty;
//从变量中获取URI
字符串url=@“https://”+DNS_NA+Variables.strURLSuffix;
//请求的时间。。。
秒表计时器=Stopwatch.StartNew();
//创建Web客户端
WebClient客户端=新的WebClient();
client.DownloadStringCompleted+=(发件人,e)=>
{
timer.Stop();
processRow(例如,Result、SERVER、Convert.ToInt32(timer.elapsedmillesons)、Convert.ToInt32(Row.upitmqy)、Output0Buffer);
CountComplete+=1;
};
Uri=新的Uri(url);
client.DownloadStringAsync(uri);
}
私有void processRow(字符串xmlDoc、长服务器、int FRAPI_时间、int PRE_正常运行时间、Output0Buffer)
{
尝试
{
XmlDocument xDoc=新的XmlDocument();
LoadXml(xmlDoc);
bool NORESPONSE=false;//如果我们走到这一步,就会得到响应,对吗?
短CPU=Convert.ToInt16(xDoc.SelectSingleNode(//server”).ChildNodes[1].InnerText);
int TOT_MEM=Convert.ToInt32(xDoc.SelectSingleNode(//server”).ChildNodes[2].InnerText)/(1024*1024);
int USE_MEM=Convert.ToInt32(xDoc.SelectSingleNode(//server”).ChildNodes[3].InnerText)/(1024*1024);
int UPTIME=Convert.ToInt32(xDoc.SelectSingleNode(//server”).ChildNodes[4].InnerText)/1000/60;
short REQUESTS=Convert.ToInt16(xDoc.SelectSingleNode(//server”).ChildNodes[5].InnerText);
bool RESET=(正常运行时间<正常运行前)?真:假;
foreach(xDoc.SelectNodes(“//server/detail/request”)中的XmlNode xNode)
{
AddRow();
buffer.SERSYSNR=服务器;
buffer.cpuuseky=CPU;
buffer.TOTMEMQY=TOT_MEM;
buffer.usemqy=USE_MEM;
buffer.upitmqy=正常运行时间;
buffer.REQCNTQY=请求;
buffer.REQMSQY=FRAPI_时间;
buffer.SERNONRSPIR=无响应;
buffer.SERRSTIR=重置;
buffer.REQSYSNR=Convert.ToInt32(xNode.ChildNodes[0].InnerText);
buffer.requipte=xNode.ChildNodes[1].InnerText;
buffer.REQURLTE=xNode.ChildNodes[2].InnerText;
buffer.REQRUNTMQY=Convert.ToInt32(xNode.ChildNodes[3].InnerText);
}
}
接住
{
//希望我们没有在foreach中抛出异常,因为已经添加了一行。。。
AddRow();
buffer.SERSYSNR=服务器;
buffer.SERNONRSPIR=true;
}
}
//公共覆盖无效CreateNewOutputRows()
// {
/*
通过对名为“Buffer”的成员变量调用AddRow方法来添加行。
例如,如果输出名为“MyOutput”,则调用MyOutputBuffer.AddRow()。
*/
//}
}

我可以在DNS上使用条件拆分,生成x个脚本组件,然后合并所有组件,但每次将新服务器添加到列表中时,我都必须编辑SSIS包。不理想。

相关连接错误报告:

将脚本任务拆分为6个是唯一有效的解决方案。我确实修复了使用DownloadStringSync时SSIS崩溃的问题,方法是切换到线程设置并只调用DownloadString。我必须确保在处理结果时锁定了Output0Buffer,这让我有点困惑。最后,在检查ProcessInputBuffer中的Buffer.EndOfRowSet()之后,我使用一个列表来存储线程并在其上循环并调用Thread.Join()

但是,在所有请求完成之前,该解决方案仍然不会转发行,这意味着如果