簡體   English   中英

SSIS package 在使用 SQL 服務器代理啟動時無法使用 C# 腳本任務處理所有行

[英]SSIS package fails to process all rows with C# Script task when started with SQL Server Agent

我需要構建一個 SSIS package 發送 HTML 格式的電子郵件,然后將電子郵件保存為 tiff 文件。 我創建了一個腳本任務來處理必要的記錄,然后將 HTML 代碼轉換為 tiff。 我已將該過程拆分為單獨的包,email 發送工作正常,將 HTML 轉換為 tiff 是導致問題的原因。

手動運行 package 時,它將毫無問題地處理所有文件。 我的測試目前大約有 315 個文件,這需要能夠處理至少 1,000 個,同時能夠一次發送多達 10,000 個。 問題是當我將 package 設置為使用 SQL 服務器代理執行時,它在 207 個文件處停止。 package部署到SSIS Catalog中的SQL Server 2019

服務器版本和資源

到目前為止我嘗試了什么

我開始將腳本放置在 SSIS package 中並部署到服務器並從一個步驟調用 package(99.999999% 的時間適用於所有包)嘗試了 32 位和 64 位運行時。 在查看執行報告時,從來沒有任何錯誤消息只是意外終止。 單擊目錄並執行 package 時,它將處理所有文件。 SQL 服務器代理正在使用代理,我還使用我的管理員憑據創建了另一個代理帳戶來測試該帳戶是否存在任何問題。

創建另一個 package 調用 package 並使用執行 Package 任務調用第一個 package,結果相同 207 個文件。 將執行進程任務更改為執行 SQL 任務,並嘗試創建用於手動啟動目錄 207 文件中的 package 的腳本。 嘗試通過其他 SSIS package 和 SQL 服務器代理直接從命令行執行腳本,結果相同 207 個文件。 如果我直接在 SQL Server Agent 之外嘗試這些方法中的任何一種,該過程運行沒有問題。

我將腳本任務轉換為控制台應用程序,它可以處理所有文件。 當從 SQL 服務器代理的任何方法調用可執行文件時,它再次停止在 207 個文件處。

我咨詢了公司的 DBA 和系統團隊,他們沒有發現任何可能導致此錯誤的原因。 似乎有某種類型的限制,無論執行方法如何 SQL 服務器代理都不允許。 我提到過查看第三方應用程序,但被告知不行。

我在下面包含了我能夠拼湊的代碼。 我是 SQL 開發人員,所以 C# 不在我的知識庫之內。 有沒有一種方法可以優化代碼,使其只使用一個線程或在每個字母之間進行清理。 在某些時候可能需要創建超過一萬個字母。

更新

我已經用新的更新代碼替換了代碼。 email 和圖像創建都包含在內,因為這是最終產品必須做的。 發送電子郵件時,有一個主要和次要的 email 地址,根據使用的 email 地址,它會更改 email 的正文包含的內容。 在查看代碼時,有一段 try catch 會在指示時發送到主節點,如果失敗則發送到輔助節點。 我猜想有一種更簡潔的方法來完成該部分,但這是我的第一個程序,因為我在 SQL 中處理其他所有內容。

感謝您的所有建議和幫助。

更新代碼

using System;
using System.Data;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Threading;
using System.Threading.Tasks;
using System.Drawing;
using System.IO;
using System.Net.Mail;
using System.Configuration;
using System.Diagnostics;

namespace DocCreator
{

    class Program
    {
        static void Main(string[] args)
        {
            var connSSIS = ConfigurationManager.ConnectionStrings["ssis_ssrs"].ConnectionString;
            int logid = 0;
            int count = 0;
            string previous = "";
            try
            {
                var connDataExtract = ConfigurationManager.ConnectionStrings["dataExtract"].ConnectionString;
                string archiveFolder = @"Folder Path";
                string project = "Mobile Pay";
                string logProc = "[dbo].[usp_EmailSentandError]";
                int rowCount = 0;
                DataTable dt = new DataTable();
                using (SqlConnection connLog = new SqlConnection(connDataExtract))
                {
                    connLog.Open();
                    SqlCommand command = new SqlCommand("etl.usp_GetEmailListID", connLog)
                    {
                        CommandType = CommandType.StoredProcedure
                    };
                    command.Parameters.Add("@Project", SqlDbType.NText).Value = project;
                    command.Parameters.Add("@NullValue", SqlDbType.Int).Value = 0;
                    using (SqlDataReader dr = command.ExecuteReader())
                    {
                        dt.Load(dr);
                    }
                    connLog.Close();
                }
               foreach (DataRow dr in dt.Rows)
                //Parallel.ForEach(dt.AsEnumerable(), dr =>
                {

                    try
                    {
                        var emailID = dr["Email_ID"];
                        var usePrimary = dr["UsePrimaryEmail"];
                        try
                        {
                            if ((bool)usePrimary)
                            {
                                try
                                {
                                    var dp = GetDataPoints(connDataExtract, (int)emailID, (bool)usePrimary);
                                    string indexfqdn = Path.Combine(archiveFolder, dp.IndexFile);
                                    string filefqdn = Path.Combine(archiveFolder, dp.ArchiveFileName);
                                    string mailBody = GetEmailBody(connDataExtract, dp.SqlProc, (int)emailID, dp.EmailBody_id);
                                    SendEmail(dp.EmailFrom, dp.EmailSubject, dp.Email, mailBody);
                                    Archive(mailBody, filefqdn, dp.FileWidth, dp.FileHeight, dp.IndexFileInsert, indexfqdn, dp.ArchiveFile);
                                    LogEmail(connDataExtract, logProc, (int)emailID, dp.EmailBody_id, 1, 1, "", 0);
                                    rowCount++;
                                }
                                catch (Exception e)
                                {
                                    try
                                    {
                                        var dp = GetDataPoints(connDataExtract, (int)emailID, false);
                                        string indexfqdn = Path.Combine(archiveFolder, dp.IndexFile);
                                        string filefqdn = Path.Combine(archiveFolder, dp.ArchiveFileName);
                                        string mailBody = GetEmailBody(connDataExtract, dp.SqlProc, (int)emailID, dp.EmailBody_id);
                                        SendEmail(dp.EmailFrom, dp.EmailSubject, dp.Email, mailBody);
                                        Archive(mailBody, filefqdn, dp.FileWidth, dp.FileHeight, dp.IndexFileInsert, indexfqdn, dp.ArchiveFile);
                                        LogEmail(connDataExtract, logProc, (int)emailID, dp.EmailBody_id, 0, 1, e.Message.ToString(), 1);
                                        rowCount++;
                                    }
                                    catch (Exception e2)
                                    {
                                        LogEmail(connDataExtract, logProc, (int)emailID, 0, 0, 0, e2.Message.ToString(), 1);
                                        Console.Clear();
                                        Console.WriteLine(e2.Message);
                                        Console.ReadLine();
                                    }
                                }
                            }
                            else
                            {
                                try
                                {
                                    var dp = GetDataPoints(connDataExtract, (int)emailID, (bool)usePrimary);
                                    string indexfqdn = Path.Combine(archiveFolder, dp.IndexFile);
                                    string filefqdn = Path.Combine(archiveFolder, dp.ArchiveFileName);
                                    string mailBody = GetEmailBody(connDataExtract, dp.SqlProc, (int)emailID, dp.EmailBody_id);
                                    SendEmail(dp.EmailFrom, dp.EmailSubject, dp.Email, mailBody);
                                    Archive(mailBody, filefqdn, dp.FileWidth, dp.FileHeight, dp.IndexFileInsert, indexfqdn, dp.ArchiveFile);
                                    LogEmail(connDataExtract, logProc, (int)emailID, dp.EmailBody_id, 0, 1, "", 0);
                                    rowCount++;
                                }
                                catch (Exception e)
                                {
                                    LogEmail(connDataExtract, logProc, (int)emailID, 0, 0, 0, e.Message.ToString(), 1);
                                    Console.Clear();
                                    Console.WriteLine(e.Message);
                                    Console.ReadLine();
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            LogEmail(connDataExtract, logProc, (int)emailID, 0, 0, 0, e.Message.ToString(), 1);
                            Console.Clear();
                            Console.WriteLine(e.Message);
                            Console.ReadLine();
                        }
                    }


                    catch (Exception e2)
                    {
                        //Console.WriteLine(e2.Message);
                        using (SqlConnection connLog2 = new SqlConnection(connSSIS))
                        {
                            connLog2.Open();
                            SqlCommand command2 = new SqlCommand("dbo.usp_InsertssisScriptTaskLog", connLog2)
                            {
                                CommandType = CommandType.StoredProcedure
                            };
                            command2.Parameters.Add("@PackageLogID", SqlDbType.Int).Value = ((ulong)logid);
                            command2.Parameters.Add("@ErrorMessage", SqlDbType.NText).Value = e2.Message.ToString();
                            command2.ExecuteNonQuery();
                            connLog2.Close();
                        }
                    }

                    count++;
                    int directThreadsCount = Process.GetCurrentProcess().Threads.Count;
                    Console.Clear();
                    Console.WriteLine(previous + Environment.NewLine+ count + "  Memory usage: " + GC.GetTotalMemory(false) + "     "  + GC.GetTotalMemory(true)  + "  Threads: " + directThreadsCount);
                    previous = count + "  Memory usage: " + GC.GetTotalMemory(false) + "     "  + GC.GetTotalMemory(true) + "  Threads: " + directThreadsCount;
                    GC.Collect(1);
                }
                Console.WriteLine("Files have been created");

            }
            catch (Exception e)
            {
                //Console.WriteLine(e.Message);
                using (SqlConnection connLog = new SqlConnection(connSSIS))
                {
                    connLog.Open();
                    SqlCommand command = new SqlCommand("dbo.usp_InsertssisScriptTaskLog", connLog)
                    {
                        CommandType = CommandType.StoredProcedure
                    };
                    command.Parameters.Add("@PackageLogID", SqlDbType.Int).Value = ((ulong)logid);
                    command.Parameters.Add("@ErrorMessage", SqlDbType.NText).Value = e.Message.ToString();
                    command.ExecuteNonQuery();
                    connLog.Close();
                }
            }
        }

        public static
        (int EmailBody_id, bool ArchiveFile, int FileHeight, int FileWidth, string IndexFile, string IndexFileInsert, string Email, string ArchiveFileName, string EmailFrom, string EmailSubject, string SqlProc)
            GetDataPoints(string connDataExtract, int Email_ID, bool UsePrimary)
        {
            string dataExtract = connDataExtract;
            int emailID = Email_ID;
            bool usePri = UsePrimary;
            using (SqlConnection connLog = new SqlConnection(dataExtract))
            {
                connLog.Open();
                SqlCommand command = new SqlCommand("etl.usp_EmailGetDataPoints", connLog)
                {
                    CommandType = CommandType.StoredProcedure
                };
                command.Parameters.Add("@Email_ID", SqlDbType.Int).Value = emailID;
                command.Parameters.Add("@UsePrimary", SqlDbType.Bit).Value = usePri;
                SqlDataReader sqlDataReader;
                int EmailBody_id = 0;
                bool ArchiveFile = true;
                int FileHeight = 0;
                int FileWidth = 0;
                string IndexFile = "";
                string IndexFileInsert = "";
                string Email = "";
                string ArchiveFileName = "";
                string EmailFrom = "";
                string EmailSubject = "";
                string SqlProc = "";
                sqlDataReader = command.ExecuteReader();
                while (sqlDataReader.Read())
                {
                    EmailBody_id = (int)sqlDataReader.GetValue(sqlDataReader.GetOrdinal("EmailBody_ID"));
                    ArchiveFile = (bool)sqlDataReader.GetValue(sqlDataReader.GetOrdinal("ArchiveFile"));
                    FileHeight = (int)sqlDataReader.GetValue(sqlDataReader.GetOrdinal("FileHeight"));
                    FileWidth = (int)sqlDataReader.GetValue(sqlDataReader.GetOrdinal("FileWidth"));
                    IndexFile = sqlDataReader.GetValue(sqlDataReader.GetOrdinal("IndexFile")).ToString();
                    IndexFileInsert = sqlDataReader.GetValue(sqlDataReader.GetOrdinal("IndexFileInsert")).ToString();
                    Email = sqlDataReader.GetValue(sqlDataReader.GetOrdinal("Email")).ToString();
                    ArchiveFileName = sqlDataReader.GetValue(sqlDataReader.GetOrdinal("ArchiveFileName")).ToString();
                    EmailFrom = sqlDataReader.GetValue(sqlDataReader.GetOrdinal("EmailFrom")).ToString();
                    EmailSubject = sqlDataReader.GetValue(sqlDataReader.GetOrdinal("EmailSubject")).ToString();
                    SqlProc = sqlDataReader.GetValue(sqlDataReader.GetOrdinal("SqlProc")).ToString();
                }
                connLog.Close();
                return (
                    EmailBody_id,
                    ArchiveFile,
                    FileHeight,
                    FileWidth,
                    IndexFile,
                    IndexFileInsert,
                    Email,
                    ArchiveFileName,
                    EmailFrom,
                    EmailSubject,
                    SqlProc);
            }
        }
        public static string GetEmailBody(string connDataExtract, string SQLProc, int Email_ID, int EmailBodyID)
        {
            string dataExtract = connDataExtract;
            string proc = SQLProc;
            int emailID = Email_ID;
            int bodyID = EmailBodyID;
            string MailBody;
            using (SqlConnection connLog = new SqlConnection(dataExtract))
            {
                connLog.Open();
                SqlCommand command = new SqlCommand(proc, connLog)
                {
                    CommandType = CommandType.StoredProcedure
                };
                command.Parameters.Add("@Email_ID", SqlDbType.Int).Value = ((ulong)emailID);
                command.Parameters.Add("@EmailBody_ID", SqlDbType.Int).Value = ((ulong)bodyID);
                SqlDataReader dataReader;
                string Output = "";
                dataReader = command.ExecuteReader();
                while (dataReader.Read())
                {
                    Output = dataReader.GetValue(0).ToString();
                }
                connLog.Close();
                MailBody = Output;
                return MailBody;
            }
        }
        public static void SendEmail(string emailFrom, string emailSubject, string emailTo, string mailBody)
        {
            string from = emailFrom;
            string subject = emailSubject;
            string to = emailTo;
            string source = mailBody;
            using (MailMessage myHtmlFormattedMail = new MailMessage())
            {
                MailAddress fromMail = new MailAddress(from);
                myHtmlFormattedMail.From = fromMail;
                myHtmlFormattedMail.Subject = subject;
                myHtmlFormattedMail.Body = source;
                foreach (var address in to.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries))
                {
                    myHtmlFormattedMail.To.Add(address);
                }
                myHtmlFormattedMail.IsBodyHtml = true;
                SmtpClient mySmtpClient = new SmtpClient();
                mySmtpClient.Send(myHtmlFormattedMail);
            }
        }
        public static void IndexFile(string indexFileInsert, string indexfqdn)
        {
            string insert = indexFileInsert;
            string fqdn = indexfqdn;
            try
            {
                if (!File.Exists(fqdn))
                {
                    using (StreamWriter sw = File.CreateText(fqdn))
                    {
                        sw.WriteLine(insert);
                    }
                }
                using (StreamWriter sw = File.AppendText(fqdn))
                {
                    sw.WriteLine(insert);
                }
            }
            catch { }
        }
        public static void LogEmail(string databaseServer, string logProc, int email_ID, int emailBodyID, int primaryEmailUsed, int emailSent, string errorMessage, int errorExists)
        {
            string dataExtract = databaseServer;
            string proc = logProc;
            int emailID = email_ID;
            int bodyID = emailBodyID;
            int usePri = primaryEmailUsed;
            int sent = emailSent;
            string error = errorMessage;
            int exists = errorExists;
            using (SqlConnection connLog = new SqlConnection(dataExtract))
            {
                connLog.Open();
                SqlCommand command = new SqlCommand(proc, connLog)
                {
                    CommandType = CommandType.StoredProcedure
                };
                command.Parameters.Add("@Email_ID", SqlDbType.Int).Value = ((ulong)emailID);
                command.Parameters.Add("@EmailBody_ID", SqlDbType.Int).Value = ((ulong)bodyID);
                command.Parameters.Add("@PrimaryEmailUsed", SqlDbType.Int).Value = ((ulong)usePri);
                command.Parameters.Add("@EmailSent", SqlDbType.Int).Value = ((ulong)sent);
                command.Parameters.Add("@ErrorMessage", SqlDbType.NText).Value = error;
                command.Parameters.Add("@ErrorExists", SqlDbType.Int).Value = ((ulong)exists);
                command.ExecuteNonQuery();
                connLog.Close();
            }
        }
        public static void StartBrowser(string mailBody, string file, int width, int height, string fileInsert, string indexFile)
        {
            try
            {
                string source = mailBody;
                string fqdn = file;
                int w = width;
                int h = height;
                string insert = fileInsert;
                string indexFQDN = indexFile;
                IndexFile(insert, indexFQDN);
                using (WebBrowser wb = new WebBrowser())
                {
                    wb.ScrollBarsEnabled = false;
                    wb.Width = w;
                    wb.Height = h;
                    wb.Visible = false;
                    wb.DocumentCompleted +=
                         (sender, e) => WebBrowser_DocumentCompleted(sender, e, fqdn);
                    wb.DocumentText = source;
                    Application.Run();
                }
            }
            finally 
            {
                Application.Exit();
            }
        }
        public static void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e, string file)
        {
            string fqdn = file;
            var webBrowser = (WebBrowser)sender;
            using (Bitmap bitmap = new Bitmap(webBrowser.Width, webBrowser.Height))
            {
                webBrowser
                    .DrawToBitmap(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height));
                bitmap.Save(fqdn, System.Drawing.Imaging.ImageFormat.Jpeg);
            }
        }
        static void Wait(int milliseconds)
        {
            using (System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer())
            {
                if (milliseconds == 0 || milliseconds < 0) return;

                // Console.WriteLine("start wait timer");
                timer1.Interval = milliseconds;
                timer1.Enabled = true;
                timer1.Start();

                timer1.Tick += (s, e) =>
                {
                    timer1.Enabled = false;
                    timer1.Stop();
                // Console.WriteLine("stop wait timer");
            };

                while (timer1.Enabled)
                {
                    System.Windows.Forms.Application.DoEvents();
                }
            }
        }
        public static void Archive(string emailBody, string file, int width, int height, string fileInsert, string indexFile, bool archiveFile)
        {
            string source = emailBody;
            string fqdn = file;
            int w = width;
            int h = height;
            string insert = fileInsert;
            string indexFQDN = indexFile;
            bool archive = archiveFile;
            if (archive)
            {
                Thread tr = new Thread(() => StartBrowser(source, fqdn, w, h, insert, indexFQDN))
                    {
                        Name = "Fred",
                        IsBackground = true
                    };
                    tr.SetApartmentState(ApartmentState.STA);
                    tr.Start();

                int wc = 800;
                while (!File.Exists(file) || wc <= 0)
                {
                    Wait(50);
                    wc--;
                };
                tr.Abort();
            }
        }

    }
}

我已經解決了這個問題,所以它滿足了我的項目的需要。 可能有更好的解決方案,但這確實有效。 使用上面的代碼,我創建了一個可執行文件並將結果集限制為前 100 個。創建了一個 ssis package 和一個 For 循環,該循環從暫存表中計算記錄並啟動可執行文件。 我進行了幾次測試,並且能夠超過項目要求的 10,000 個限制。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM