问题描述
尝试从Twilio API中读取记录,然后将其用于SSIS数据流中并将记录保存在sql Server数据库中。使用https://www.twilio.com/docs/sms/api/message-resource#read-multiple-message-resources中的api文档,我已经能够阅读消息,但是对下一步的工作有些困惑,我只想将其用作数据流的来源,因此不要尝试做任何花哨的事情在.net中,更多的是sql专家,所以对C#不太熟悉。
我是否一直认为这太简单了?假设我能够读取消息(看起来好像不是JSON格式,已经使用Twilio.dll拆分了各个字段),然后将其放入变量中,然后循环遍历每一行并传递到输出缓冲区。
本质上,正在尝试这样的事情:
public override void CreateNewOutputRows()
{
string accountSid = "AAAA";
string authToken = "1111";
TwilioClient.Init(accountSid,authToken);
var response = MessageResource.Read();
foreach (var msg in response)
{
Output0Buffer.AddRow();
Output0Buffer.ID = msg.Sid.ToString();
Output0Buffer.Message = msg.Body.ToString();
}
}
```
解决方法
这是一个不使用Twilio库并且不使用数据流的示例。
我们基本上正在寻找类似的东西:
- 截断我们正在加载的表
- 我们将使用For循环容器,因为我们必须考虑分页。
- 进行REST调用的C#脚本任务
- 用于解析JSON的存储过程,插入到表中并评估下一个url值,然后将其返回,以查看是否需要再次处理。
Twilio在响应中返回的默认值为50条记录,最大为1000条。如果您想要的不是默认值,则可以使用URL参数“?PageSize = 60”进行更改。如果有更多记录,则特定的页面大小,响应将包括下一个要获取下一组记录的URL。
两个变量:
NextUrl设置为
https://api.twilio.com/2010-04-01/Accounts/{AccountSid}/Messages.json
用于循环容器
一旦NextUrl = STOP,循环将停止。我们在存储过程中进行处理。插入数据后,我们检查该值,如果为NULL,则将其设置为STOP。
传入URL,在脚本中设置apiResponse使其返回。
Main()的代码
try
{
string apiUrl = Dts.Variables["NextUrl"].Value.ToString();
string userName = ""; //accountSid found in Twilio account console
string passwd = ""; //authToken found in Twilio account console
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
byte[] authToken = Encoding.ASCII.GetBytes($"{userName}:{passwd}");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",Convert.ToBase64String(authToken));
HttpResponseMessage response;
// Execute the REST GET
response = client.GetAsync(apiUrl).GetAwaiter().GetResult();
// Get the JSON response.
string contentString = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
Dts.Variables["apiResponse"].Value = contentString; //Passing the response back out.
Dts.TaskResult = (int)ScriptResults.Success;
}
catch (Exception ex)
{
//This code will cause the ssis to fail and bubble back out the error from this code
Dts.Events.FireError(-1,"Error",ex.Message,String.Empty,0);
Dts.TaskResult = (int)ScriptResults.Failure;
}
使用NVARCHAR(MAX)参数创建一个存储过程,以接受apiResponse并返回NextUrl值。该任务将类似于:
参数映射:
结果集:
然后,存储过程本身将类似于:
CREATE PROCEDURE [dbo].[InsertTwilioMessage]
@apiResponse NVARCHAR(MAX)
AS
DECLARE @NextUrl NVARCHAR(2000);
INSERT INTO [dbo].[TwilioMessage] (
[body],[num_segments],[direction],[from],[date_updated],[price],[error_message],[uri],[account_sid],[num_media],[to],[date_created],[status],[sid],[date_sent],[messaging_service_sid],[error_code],[price_unit],[api_version]
)
SELECT [rsp].[body],[rsp].[num_segments],[rsp].[direction],[rsp].[from],[rsp].[date_updated],[rsp].[price],[rsp].[error_message],[rsp].[uri],[rsp].[account_sid],[rsp].[num_media],[rsp].[to],[rsp].[date_created],[rsp].[status],[rsp].[sid],[rsp].[date_sent],[rsp].[messaging_service_sid],[rsp].[error_code],[rsp].[price_unit],[rsp].[api_version]
FROM OPENJSON(@apiResponse,'$.messages') --data is in the messages array
WITH (
[body] NVARCHAR(255) '$.body',[num_segments] NVARCHAR(255) '$.num_segments',[direction] NVARCHAR(255) '$.direction',[from] NVARCHAR(255) '$.from',[date_updated] NVARCHAR(255) '$.date_updated',[price] NVARCHAR(255) '$.price',[error_message] NVARCHAR(255) '$.error_message',[uri] NVARCHAR(255) '$.uri',[account_sid] NVARCHAR(255) '$.account_sid',[num_media] NVARCHAR(255) '$.num_media',[to] NVARCHAR(255) '$.to',[date_created] NVARCHAR(255) '$.date_created',[status] NVARCHAR(255) '$.status',[sid] NVARCHAR(255) '$.sid',[date_sent] NVARCHAR(255) '$.date_sent',[messaging_service_sid] NVARCHAR(255) '$.messing_serivce_sid',[error_code] NVARCHAR(255) '$.error_code',[price_unit] NVARCHAR(255) '$.price_unit',[api_version] NVARCHAR(255) '$.api_version'
) AS [rsp];
SELECT @NextUrl = [next_page_uri]
FROM
OPENJSON(@apiResponse)
WITH (
[next_page_uri] NVARCHAR(2000) '$.next_page_uri'
);
-- we check for null of NextUrl and return STOP to stop the for loop
--if not we return out the Url to go back around and get more data
SELECT CASE WHEN @NextUrl IS NOT NULL THEN CONCAT('https://api.twilio.com',@NextUrl)
ELSE 'STOP'
END AS [NextUrl];
SSIS变量NextUrl get被存储过程返回的内容覆盖。如果不等于STOP,则继续执行for循环,现在将该URL传递到脚本任务中以获取下一组数据,依此类推...
,最终可以使它在C#中工作。问题在于正在使用的dll版本在最新版本之间无法正常工作。