简体   繁体   English

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

[英]Why is not my stored procedure executing CLR method with some id's?

In short, I have a CLR method for send emails to users from SQL Server. 简而言之,我有一种CLR方法,用于从SQL Server向用户发送电子邮件。 I have all my data information about body, attachments, subject, emails, etc in my SQL Server tables. 我的SQL Server表中包含有关正文,附件,主题,电子邮件等的所有数据信息。 Well, I'm doing an app in C# to do this, I haven't get troubles for save information with stored procedures in tables but when I want to execute my SP sending id(mail). 好吧,我正在用C#编写一个应用程序来做到这一点,我没有麻烦将信息存储在表中的存储过程中,但是当我想执行SP发送ID(邮件)时。 This says 'Command completed successfully' but mail don't send. 这表示“命令已成功完成”,但邮件未发送。 Then I test executing my SP from SQL Server manually and send correctly some id's and some don't 'watch' my method for send, because this execute commands correctly but do anything. 然后,我测试从SQL Server手动执行SP,并正确发送一些ID,而某些不“监视”我的发送方法,因为这可以正确执行命令,但可以执行任何操作。 Why is happening this? 为什么会这样呢? Someone has have this issue before?? 有人以前有这个问题吗?

This is my CLR Method 这是我的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;
    }

This my Stored Procedure 这是我的存储过程

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

不工作 做工完美

Both ID's exist in my sql table like valid mails. 两个ID都像有效邮件一样存在于我的sql表中。 Ignore names of SP is for privacity they have same name in CLR method and Stored Procedure 出于安全考虑,请忽略SP的名称,它们在CLR方法和存储过程中具有相同的名称

I've got this Exception in SQL Server. 我在SQL Server中有此异常。

Mens 6522, Nivel 16, Estado 1, Procedimiento ZeusFW_EmailqueueUnit_SendOutError, Línea 2 Mens 6522,Nivel 16,Estado 1,Procedimiento ZeusFW_EmailqueueUnit_SendOutError,Línea2
A .NET Framework error occurred during execution of user-defined routine or aggregate "ZeusFW_EmailqueueUnit_SendOutError": 在执行用户定义的例程或聚合“ ZeusFW_EmailqueueUnit_SendOutError”期间发生.NET Framework错误:

System.IO.IOException: El sistema no puede ponerse en contacto con un controlador de dominio para que atienda la solicitud de autenticación. System.IO.IOException:紧急情况下的控制权的联系制度。 Inténtelo de nuevo más tarde. Inténtelode nuevo主要。

System.IO.IOException: System.IO.IOException:
en System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) zh-cn System.IO .__ Error.WinIOError(Int32 errorCode,可能是StringFullPath)
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) zh-cn System.IO.FileStream.Init(字符串路径,FileMode模式,FileAccess访问,Int32权限,布尔useRights,FileShare共享,Int32 bufferSize,FileOptions选项,SECURITY_ATTRIBUTES secAttrs,字符串msgPath,布尔bFromProxy)
en System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy) zh-cn System.IO.FileStream..ctor(字符串路径,FileMode模式,FileAccess访问,FileShare共享,Int32 bufferSize,FileOptions选项,String msgPath,布尔bFromProxy)
en System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share) zh-cn System.IO.FileStream..ctor(字符串路径,FileMode模式,FileAccess访问,FileShare共享)
en System.Net.Mail.AttachmentBase.SetContentFromFile(String fileName, String mediaType) zh-cn System.Net.Mail.AttachmentBase.SetContentFromFile(字符串fileName,字符串mediaType)
en System.Net.Mail.Attachment..ctor(String fileName) zh-cn System.Net.Mail.Attachment..ctor(字符串fileName)
en ZeusFrameworkSmtp.ZeusFrameworkSmtp.Send(String& error) zh-cn ZeusFrameworkSmtp.ZeusFrameworkSmtp.Send(字符串和错误)
en AssemblyZeusSMTP.AssemblyZeusSMTP.ZeusFW_EmailqueueUnit_SendOutError(SqlInt32 id_email, SqlString& sError) zh_cn AssemblyZeusSMTP.AssemblyZeusSMTP.ZeusFW_EmailqueueUnit_SendOutError(SqlInt32 id_email,SqlString&sError)

Here are some things to look at: 这里有一些事情要看:

  1. Please use the Sql* types instead of the native .NET types for input and output parameters for the SQLCLR public methods. 对于SQLCLR公共方法的输入和输出参数,请使用Sql*类型而不是本机.NET类型。 So the signature should be: 因此签名应为:

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

    You can get the native values out of any of those types via the .Value property that they all have (eg id_email.Value ). 您可以通过它们都具有的.Value属性(例如id_email.Value )从任何这些类型中获取本机值。

  2. You went through the trouble of passing back the status code, so capture it so you can see more of what is going on. 您遇到了传回状态代码的麻烦,因此请捕获它,以便您可以查看正在发生的事情。 In the C# code, assign a non-zero value to mReturn based on bresult : 在C#代码中,根据bresultmReturn分配一个非零值:

     if (bresult) { mReturn = 1; } else { mReturn = 2; } 

    And then change your T-SQL to be: 然后将您的T-SQL更改为:

     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]; 
  3. Looking at the posted code, it seems like the only ways to get an empty string for @sError (is it really empty?) are: 查看发布的代码,似乎为@sError获取空字符串的唯一方法(它真的为空吗?)是:

    1. email.Send() is actually passing back a non-empty string of white-space and/or other non-printable characters. email.Send()实际上是传回一个非空的空白字符串和/或其他不可打印的字符。 The T-SQL shown above has been adjusted to check for this. 上面显示的T-SQL已进行调整以进行检查。
    2. the code is getting an exception, in which case you should see something in the Windows Event Log (since you are saving an entry there). 代码出现异常,在这种情况下,您应该在Windows事件日志中看到一些内容(因为您将条目保存在此)。 Have you checked the Windows Event Log? 您是否检查过Windows事件日志?
  4. Is there any logging in the Zeus framework that you can check? 您可以检查Zeus框架中的任何日志记录吗?
  5. Most importantly: why are you sending emails from SQLCLR when SQL Server has a built-in function for this, one that is asynchronous? 最重要的是:当SQL Server具有内置功能(异步功能)时,为什么从SQLCLR发送电子邮件? It can handle file attachments, HTML email bodies, etc. Please look into swapping out this SQLCLR Stored Procedure for a T-SQL Stored Procedure that calls sp_send_dbmail (introduced in SQL Server 2008, or possibly even 2005). 它可以处理文件附件,HTML电子邮件正文等。请考虑将这个SQLCLR存储过程换成调用sp_send_dbmail的T-SQL存储过程(在SQL Server 2008甚至2005中引入)。

Other notes: 其他说明:

  • Life will be easier, and your code more readable, if you stop prefixing variables with the datatype. 如果您停止为数据类型添加变量前缀,则生活会更轻松,代码也更易读。 So use Result instead of mReturn , Result instead of bResult , and ErrorMessage instead of sError . 因此,使用Result ,而不是mReturnResult不是bResultErrorMessage而不是sError This goes for working in both C# and T-SQL. 这适用于C#和T-SQL。
  • There is no need to subtract 1 from a Count in a loop as that forces you to use <= instead of just < . 无需在循环中从Count减去1 ,因为这会迫使您使用<=而不是< Using j < ds.Tables[1].Rows.Count is logically the same, one less (unnecessary) operation, and more readable :-). 使用j < ds.Tables[1].Rows.Count在逻辑上是相同的,减少了一次(不必要的)操作,并且更具可读性:-)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM