为什么我的存储过程不执行带有一些id的CLR方法?

时间:2016-11-25 14:20:21

标签: c# sql-server stored-procedures .net-assembly sqlclr

简而言之,我有一个CLR方法,用于从SQL Server向用户发送电子邮件。我在SQL Server表中拥有有关正文,附件,主题,电子邮件等的所有数据信息。好吧,我正在用C#做一个应用程序来执行此操作,我没有遇到有关表中存储过程的保存信息的麻烦,但是当我想执行我的SP发送ID(邮件)时。这说'命令已成功完成'但邮件不发送。然后我测试从SQL Server手动执行我的SP并正确发送一些id和一些不“看”我的发送方法,因为这执行命令正确但做任何事情。为什么会这样?有人在此之前遇到过这个问题吗?

这是我的CLR方法

[SqlProcedure]
    public static int CustomMethod(int id_email, out string sError)
    {
        int mReturn = 0;
        DataSet ds = new DataSet();
        sError = string.Empty;
        Dictionary<int, string> ListFile = new Dictionary<int, string>();
        try
        {                
            ds = retornarQuery(strQuery: "ZeusFW_Email_List " + id_email);
            if (ds.Tables[0].Rows.Count > 0)
            {
                for (int i = 0; i <= ds.Tables[0].Rows.Count - 1; i++)
                {
                    DataRow row = ds.Tables[0].Rows[i];
                    string ds_to_name = (string)row["ds_to_name"];
                    string ds_to_email = (string)row["ds_to_email"];
                    string ds_cc_email = (string)row["ds_cc_email"];
                    string ds_bcc_email = (string)row["ds_bcc_email"];
                    string ds_idiom = (string)row["ds_idiom"];
                    string ds_subject = (string)row["ds_subject"];
                    string ds_body = (string)row["ds_body"];
                    int am_sent_times = (int)row["am_sent_times"];
                    int in_process = (int)row["in_process"];
                    int am_email_port = (int)row["am_email_port"];
                    string ds_email_host = (string)row["ds_email_host"];
                    string ds_email_user = (string)row["ds_email_user"];
                    string ds_email_password = (string)row["ds_email_password"];
                    int am_email_html = (int)row["am_email_html"];
                    int am_email_ssl = (int)row["am_email_ssl"];
                    string ds_email_name = (string)row["ds_email_name"];
                    string ds_email_xsl = (string)row["ds_email_xsl"];
                    int in_email_log = (int)row["in_email_log"];
                    DeliveryNotificationOptions am_notificationoptions = NotificationOptions((int)row["am_notificationoptions"]);
                    MailPriority am_priority = Priority((int)row["am_priority"]);
                    if (in_process == 0 && am_email_html == 1)
                    {
                        ds_body = DoXSLT(ds_body, ds_email_xsl);
                    }
                    ZeusFrameworkSmtp.ZeusFrameworkSmtp email = new ZeusFrameworkSmtp.ZeusFrameworkSmtp();
                    email.AddFrom = ds_email_user;
                    email.AddName = ds_email_name;
                    email.AddTo.Add(ds_to_email);
                    if (ds_cc_email != null || !ds_cc_email.Equals("")) email.AddCC = ds_cc_email;
                    if (ds_bcc_email != null || !ds_bcc_email.Equals("")) email.AddBcc = ds_bcc_email;
                    if (am_sent_times > 0) { ds_subject = "Re#" + am_sent_times + " " + ds_subject; }
                    email.Subject = ds_subject;
                    email.Body = ds_body;
                    email.BodyHtml = (am_email_html == 0 ? false : true);
                    email.Server = ds_email_host;
                    email.Port = am_email_port;
                    email.User = ds_email_user;
                    email.Password = ds_email_password;
                    email.EnableSsl = (am_email_ssl == 0 ? false : true); ;
                    email.NotificationOptions = am_notificationoptions;
                    email.Priority = am_priority;
                    am_sent_times = am_sent_times + 1;
                    if (ds.Tables[1].Rows.Count > 0)
                    {
                        for (int j = 0; j <= ds.Tables[1].Rows.Count - 1; j++)
                        {
                            DataRow rowAttachments = ds.Tables[1].Rows[j];
                            if (id_email == (int)rowAttachments["id_email"])
                            {
                                if ((int)rowAttachments["in_delete_file"] == 1) ListFile.Add(j, (string)rowAttachments["ds_full_path"]);
                                email.AddAttachments.Add((string)rowAttachments["ds_full_path"]);
                            }
                        }
                    }
                    bool bresult = email.Send(out sError);
                    //if (bresult) { mReturn = 1; Database.ZeusFW_Email_Update(id_email, am_sent_times, sError, in_email_log).Run(); }
                    if (string.IsNullOrEmpty(sError) || sError.Equals("ESTOY EJECUTANDO EL METODO")) sError = "Operación completada con éxito.";
                    if (ListFile.Count > 0)
                    {
                        foreach (KeyValuePair<int, string> item in ListFile)
                        {
                            if (item.Key == 1) File.Delete(item.Value.ToString());
                        }
                        ListFile.Clear();
                    }
                }
            }
            else sError = "No se encontró el ID";
        }
        catch (Exception ex)
        {
            StringBuilder s = new StringBuilder();
            //sError = sError + "-" + "Error executing SQL statement information: " + ex.Message + "id_email : " + id_email.ToString() + "Conn : " + Database.ConnectionString + ex.StackTrace.ToString();

            LogWindows _LogWindows = new LogWindows();
            _LogWindows.Save("Zeus", sError, System.Diagnostics.EventLogEntryType.Error);
            //SqlContext.Pipe.Send("Error executing SQL statement information: " + ex.Message + "id_email> " + id_email_aux.ToString() + "Conn>" + Database.ConnectionString);
        }
        return mReturn;
    }

这是我的存储过程

CREATE PROCEDURE [dbo].[CustomMethod]
@id_email int
,@sError nvarchar(2000)=NULL OUTPUT
WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [AssemblyNamespace].[AssemblyNamespace.AssemblyNamespace1].[CustomMethod]
GO

Don't Work Work perfect

这两个ID都存在于我的sql表中,就像有效的邮件一样。忽略SP的名称是为了它们在CLR方法和存储过程

中具有相同名称的特权

我在SQL Server中遇到此异常。

  

Mens 6522,Nivel 16,Estado 1,Procedimiento ZeusFW_EmailqueueUnit_SendOutError,Línea2
  执行用户定义的例程或聚合“ZeusFW_EmailqueueUnit_SendOutError”期间发生.NET Framework错误:

     

System.IO.IOException:El sistema no puede ponerse en contacto con un controlador de dominio para que atienda la solicituddeuticnticación。 Inténtelodenuevomástarde。

     

System.IO.IOException:
    en System.IO .__ Error.WinIOError(Int32 errorCode,String maybeFullPath)
    en System.IO.FileStream.Init(String path,FileMode mode,FileAccess access,Int32 rights,Boolean useRights,FileShare share,Int32 bufferSize,FileOptions options,SECURITY_ATTRIBUTES secAttrs,String msgPath,Boolean bFromProxy)
    en System.IO.FileStream..ctor(String path,FileMode mode,FileAccess access,FileShare share,Int32 bufferSize,FileOptions options,String msgPath,Boolean bFromProxy)
    en System.IO.FileStream..ctor(字符串路径,FileMode模式,FileAccess访问,FileShare共享)
    en System.Net.Mail.AttachmentBase.SetContentFromFile(String fileName,String mediaType)
    en System.Net.Mail.Attachment..ctor(String fileName)
    en ZeusFrameworkSmtp.ZeusFrameworkSmtp.Send(String&amp; error)
    en AssemblyZeusSMTP.AssemblyZeusSMTP.ZeusFW_EmailqueueUnit_SendOutError(SqlInt32 id_email,SqlString&amp; sError)

1 个答案:

答案 0 :(得分:3)

以下是一些要注意的事项:

  1. 请使用Sql*类型而不是本机.NET类型作为SQLCLR公共方法的输入和输出参数。签名应该是:

    public static SqlInt32 CustomMethod(SqlInt32 id_email, out SqlString sError)
    

    您可以通过.Value所有的id_email.Value属性从这些类型中获取原生价值(例如mReturn)。

  2. 您经历了传回状态代码的麻烦,因此捕获它以便您可以看到更多正在发生的事情。在C#代码中,根据bresultif (bresult) { mReturn = 1; } else { mReturn = 2; } 分配一个非零值:

    DECLARE @id_email INT,
            @sError NVARCHAR(4000),
            @return_code INT;
    
    SET @id_email = 37;
    
    EXEC @return_code = dbo.ZeusFW_EmailQueueUnit_SendOutError
            @id_email,
            @sError OUTPUT;
    
    SELECT @return_code AS [ReturnCode],
           N'~' + @sError + N'~' AS [ErrorMessage],
           DATALENGTH(@sError) AS [ErrorMessageBytes];
    

    然后将您的T-SQL更改为:

    @sError
  3. 查看已发布的代码,似乎唯一获取email.Send()空字符串的方法(它真的是空的吗?)是:

    1. Result实际上是传回非空白字符串和/或其他不可打印字符的字符串。上面显示的T-SQL已经过调整以检查这一点。
    2. 代码正在获得异常,在这种情况下,您应该在Windows事件日志中看到一些内容(因为您在那里保存了一个条目)。你检查过Windows事件日志吗?
  4. 您可以查看Zeus框架中的任何日志记录吗?
  5. 最重要的是:当SQL Server具有内置函数时,为什么要从SQLCLR发送电子邮件,这是异步的?它可以处理文件附件,HTML电子邮件正文等。请查看更换此SQLCLR存储过程以获取调用sp_send_dbmail的T-SQL存储过程(在SQL Server 2008中引入,甚至可能在2005年引入)。
  6. 其他说明:

    • 如果停止使用数据类型为变量添加前缀,那么生活会更容易,并且您的代码更具可读性。因此,请使用mReturn代替ResultbResult代替ErrorMessagesError代替1。这适用于C#和T-SQL。
    • 无需从循环中的Count中减去<=,因为这会强制您使用<而不是j < ds.Tables[1].Rows.Count。使用.mytable tbody tr:nth-child(1) td:nth-child(5) { /* Styles goes here */ } 在逻辑上是相同的,少一个(不必要的)操作,并且更具可读性: - )。