SSIS 脚本任务抛出死锁错误

SSIS Script Task is throwing deadlock error

我正在尝试查询数据库并发送电子邮件正文中的内容。对于我的用例,我尝试遵循 here。但是当我尝试 运行 包时,它会抛出死锁错误。任何人都可以建议我缺少什么

脚本如下

namespace ST_ac39a1a4cb6047819cc46d683db46ac6
{
    [Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
    public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
    {

        enum ScriptResults
        {
            Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
            Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
        }

        public void Main()
        {
            Variables varCollection = null;

            string User_Recepient_Email_ID = Dts.Variables["User::UserEml"].Value.ToString();

            Dts.VariableDispenser.LockForWrite("User::EmailData");
            Dts.VariableDispenser.GetVariables(ref varCollection);
            var data = varCollection["User::EmailData"].Value;

            OleDbDataAdapter da = new OleDbDataAdapter();
            DataTable dt = new DataTable();
            da.Fill(dt, varCollection["User::EmailData"].Value);

            SendMailMessage("loadJob@xyz.com", User_Recepient_Email_ID, "ETL Load Status Report", ConvertDataTableToHTML(dt), true, "smtp.xxxxxxxx.org");

            Dts.TaskResult = (int)ScriptResults.Success;
        }


        public static string ConvertDataTableToHTML(DataTable dt)
        {
            string html = "<table border ='1'>";
            //add header row
            html += "<tr>";
            for (int i = 0; i < dt.Columns.Count; i++)
                html += "<th>" + dt.Columns[i].ColumnName + "</th>";
            html += "</tr>";
            //add rows
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                html += "<tr style='color:blue;'>";
                for (int j = 0; j < dt.Columns.Count; j++)
                    html += "<td>" + dt.Rows[i][j].ToString() + "</td>";
                html += "</tr>";
            }
            html += "</table>";
            return html;
        }
        private void SendMailMessage(string From, string SendTo, string Subject, string Body, bool IsBodyHtml, string Server)
        {
            MailMessage htmlMessage;
            SmtpClient mySmtpClient;

            htmlMessage = new MailMessage(From, SendTo, Subject, Body);
            htmlMessage.IsBodyHtml = IsBodyHtml;

            mySmtpClient = new SmtpClient(Server);
            mySmtpClient.Credentials = CredentialCache.DefaultNetworkCredentials;
            mySmtpClient.Send(htmlMessage);
        }   
    }
}

和任务脚本属性

当运行打包时,错误是

Error: 0xC001405C at Script Task: A deadlock was detected while trying to lock variables "User::EmailData" for read/write access. A lock cannot be acquired after 16 attempts. The locks timed out.`

Error: 0xC001405D at Script Task: A deadlock was detected while trying to lock variables "System::InteractiveMode" for read access and variables "User::EmailData" for read/write access. A lock cannot be acquired after 16 attempts. The locks timed out.

Error: 0x1 at Script Task: A deadlock was detected while trying to lock variables "User::EmailData" for read/write access. A lock cannot be acquired after 16 attempts. The locks timed out. Task failed: Script Task

Warning: 0x80019002 at Foreach Loop each User: SSIS Warning Code DTS_W_MAXIMUMERRORCOUNTREACHED. The Execution method succeeded, but the number of errors raised (5) reached the maximum allowed (1); resulting in failure. This occurs when the number of errors reaches the number specified in MaximumErrorCount. Change the MaximumErrorCount or fix the errors. Warning: 0x80019002 at SurplusMouse_EmailOrderDetail: SSIS Warning Code DTS_W_MAXIMUMERRORCOUNTREACHED. The Execution method succeeded, but the number of errors raised (5) reached the maximum allowed (1); resulting in failure. This occurs when the number of errors reaches the number specified in MaximumErrorCount. Change the MaximumErrorCount or fix the errors. SSIS package

编辑

下面是查询

SELECT cus.CustomerNumber as CustomerNumber,cus.Location as ReceivingLocation, 
       i.StrainName as StrainName,i.StrainCode as StrainCode,i.Age as Age,
       i.Sex as Sex,i.Genotype as Genotype,i.RoomNumber as SentFrom,io.OrderQuantity as OrderQuantity
FROM [dbo].[MouseOrder] mo
JOIN [dbo].[Customer] cus on cus.Customer_ID = mo.CustomerId
JOIN [dbo].[InventoryOrder] io on io.OrderId = mo.MouseOrder_ID
JOIN [dbo].[Inventory] i on i.Inventory_ID =  io.InventoryId 
WHERE mo.OrderDate = convert(date,getdate() AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time') and mo.SAMAccountEmail = ?

有更好的方法。

步骤:

  1. 创建 SQL 将生成 (X)HTML 正文的服务器存储过程 通过 XML/XQuery.
  2. 发送电子邮件
  3. 通过 SSIS 执行 SQL 任务调用该 sp,并将其输出分配给 SSIS 变量。
  4. 调用 SSIS 脚本 任务传递第 2 步中包含 (X)HTML 电子邮件正文的变量以发送电子邮件。

好处:

  • 没有字符串连接。
  • 不用担心 NULL 值。
  • 非常容易创建,非常容易维护。
  • UI 样式通过 CSS.
  • 控制

这是一个概念性的例子。

SQL

DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, [Name] VARCHAR(20), Number CHAR(5), [Address] VARCHAR(100));
INSERT INTO @tbl (Name, Number, Address) VALUES
('Bob  ', '12345' ,'1 Street, Town'),
('John ', '23456' , NULL),
('Scott', '34567' ,'3 Avenue, City');

DECLARE @xhtmlBody XML
   , @body NVARCHAR(MAX)
   , @tableCaption VARCHAR(30) = 'Customers list';

SET @xhtmlBody = (SELECT (
SELECT * FROM @tbl 
FOR XML PATH('row'), TYPE, ROOT('root'))
.query('<html><head>
            <meta charset="utf-8"/>
            (: including embedded CSS styling :)
            <style>
            table <![CDATA[ {border-collapse: collapse;  width: 300px;} ]]>
            th <![CDATA[ {background-color: #4CAF50; color: white;} ]]>
            th, td <![CDATA[ { text-align: left; padding: 8px;} ]]>
            tr:nth-child(even) <![CDATA[ {background-color: #f2f2f2;} ]]>
            #green <![CDATA[ {background-color: lightgreen;} ]]>
         </style>
         </head>
         <body>
<table border="1">
   <caption><h2>{sql:variable("@tableCaption")}</h2></caption>
   <thead>
      <tr>
        <th>No.</th>
        <th>Name</th>
        <th>Number</th>
        <th>Address</th>
      </tr>
   </thead>
   <tbody>
{
    for $row in /root/row
    return <tr>
            <td>{data($row/ID)}</td>
            <td>{data($row/Name)}</td>
            <td>{data($row/Number)}</td>
            <td>{data($row/Address)}</td>
        </tr>
}
</tbody></table></body></html>'));

SELECT @xhtmlBody;

SET @body = CAST(@xhtmlBody AS NVARCHAR(MAX));

根据您得到的结果,错误是从您与变量交互的方式中逐渐出现的。您提供的代码是他在 2005 年时代必须做的事情,尽管当时已经 VB.NET 因为 C# 不是一个选项。您应该能够通过 Dts.Variables 集合直接访问变量,然后获取它们的 Value - 根据需要转换为字符串或保留为对象类型。

        string User_Recepient_Email_ID = Dts.Variables["User::UserEml"].Value.ToString();
        var data = Dts.Variables["User::EmailData"].Value;

        OleDbDataAdapter da = new OleDbDataAdapter();
        DataTable dt = new DataTable();
        da.Fill(dt, data);

看起来您实际上并没有写入值,所以我会在第一个屏幕截图中将它们从 ReadWrite 更改为 ReadOnly。