代码之家  ›  专栏  ›  技术社区  ›  spinon

子串错误,但不使用子串

  •  0
  • spinon  · 技术社区  · 14 年前

    我有以下代码:

    public static long CreateVendorsEmailJob(List<Recipient> recipients, string subject, string body)
            {
                long emailJobId;
    
                using (var connection = new MySqlConnection(ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString))
                {
                    connection.Open();
    
                    // create email job
                    using (var command = new MySqlCommand())
                    {
                        command.Connection = connection;
                        command.CommandType = CommandType.Text;
                        command.CommandText =
                            string.Format(
                                "INSERT INTO email_job (parent_id, job_type_lookup_id, from_email, from_name, subject, body_type_lookup_id, body, status_lookup_id, total_emails, persist_addresses) VALUES ({0}, {1}, '{2}', '{3}', '{4}', {5}, '{6}', {7}, {8}, {9})",
                                5000,
                                745,
                                "info@domain.com",
                                "Company Management System",
                                subject,
                                22,
                                body,
                                27,
                                recipients.Count,
                                1);
    
                        command.ExecuteNonQuery();
    
                        emailJobId = command.LastInsertedId;
                    }
    
                    using (var command = new MySqlCommand())
                    {
                        command.Connection = connection;
                        command.CommandType = CommandType.Text;
    
                        string commandText = "INSERT INTO email_job_email (job_id, comm_optin_id, name, email) VALUES ";
                        var valuesToAdd = new List<string>();
    
                        recipients.ForEach(r => valuesToAdd.Add(string.Format("({0}, {1}, '{2}', '{3}')", emailJobId, r.RecipientId, r.Name, r.EmailAddress)));
    
                        commandText += string.Join(",", valuesToAdd.ToArray());
    
                        command.CommandText = commandText;
                        command.ExecuteNonQuery();
                    }
    
                    connection.Close();
                }
    
                return emailJobId;
            }
    

    这段代码在为一个任务运行时运行良好,但在为另一个任务运行相同的代码时却不起作用。它给了我以下错误:

    Index and length must refer to a location within the string.
    Parameter name: length
    

    现在我每次运行它的唯一区别是消息的主题和正文。它们存储在资源文件中,并在调用方法时传入。但我似乎搞不懂的是,这个例外会在哪里发生。它是一个windows服务,运行在远程机器上,所以调试起来并不那么容易,而且我没有一个好的开发环境来镜像它们。

    我以前看到的错误,但似乎总是与某种子字符串操作。文本只是一些基本的东西,其中一个和另一个非常相似,所以我甚至看不出为什么会导致这个。

    有什么想法或者为什么?

    编辑:好吧,等我有了一个惊喜,意识到我可以在这里打印出一个堆栈跟踪,这就是我得到的-

    at MySql.Data.MySqlClient.MySqlTokenizer.NextParameter()
       at MySql.Data.MySqlClient.Statement.InternalBindParameters(String sql, MySqlParameterCollection parameters, MySqlPacket packet)
       at MySql.Data.MySqlClient.Statement.BindParameters()
       at MySql.Data.MySqlClient.PreparableStatement.Execute()
       at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
       at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery()
       at PCM.AutoWorkEngine.Tasks.RecurringVendorMailer.Entities.DataMappers.EmailJobMapper.CreateVendorsEmailJob(List`1 recipients, String subject, String body) in C:\Projects\PCM\PCM.AutoWorkEngine.RecurringVendorMailer\Entities\DataMappers\EmailJobMapper.cs:line 65
       at PCM.AutoWorkEngine.Tasks.RecurringVendorMailer.HOAVendorTask.Execute() in C:\Projects\PCM\PCM.AutoWorkEngine.RecurringVendorMailer\HOAVendorTask.cs:line 24
       at PCM.AutoWorkEngine.AutoWorkEngineService.Start() in C:\Projects\PCM\PCM.AutoWorkEngine\AutoWorkEngineService.cs:line 80 
    

    我不太熟悉的是为MySql准备的语句。我不想用那样的东西。但我在课文中有单引号。但我在两篇课文中都有,而且第一篇的效果很好,所以不确定是不是这样。我用反斜杠将它们转义到资源文件中。

    3 回复  |  直到 14 年前
        1
  •  2
  •   Community CDub    8 年前

    你需要对受试者和尸体进行消毒。例如,如果你的主题是

    ');
    你会遇到麻烦的。例如,请参见 here here .
        2
  •  0
  •   Michael Petrotta user3140870    14 年前

    你可能会发现 this MySQL bug report 有趣的是:

    带转义反斜杠的SQL字符串。

    示例:

    insert into pb_im set m_from=1, m_to=1, m_content='\\=';
    insert into pb_im set m_from=1, m_to=1, m_content='\\'; /* works sometimes, fail somtimes */

    字符串中的反斜杠-连接器返回选项
    在Query Browser/CLI/connector 5.x上工作,在6.0.3上失败:

    索引和长度必须引用字符串中的位置。
    参数名称:长度

    在System.String.InternalSubStringWithChecks(Int32开始索引,Int32长度,布尔值 故障检查)
    在MySql.Data.MySqlClient.MySqlTokenizer.NextParameter()

    我不清楚这是不是每一个修正;错误报告是模棱两可的。不过,您至少应该检查以确保使用的是最新的MySQL libs。

    也许可以使用任何包含反斜杠的字符串-看看是否可以隔离问题数据。

        3
  •  0
  •   Fadrian Sudaman    14 年前

    这通常是由包含特殊字符的字符串引起的,而名称通常是罪魁祸首,例如O'Reilly。如果INSERT…VALUES语句中有该字符串,则会报告奇怪的错误。还有其他特殊字符,如&等,需要注意。

    解决问题的两个建议: -使用参数绑定而不是构建自己的SQL字符串 -但是,如果必须使用上述方法,请尝试编写一个小例程,该例程在用于参数之前自动转义字符串。如。

    private string EscapeSQLParamString(string param)
    {
     ...............
     return escapedString;
    }
    

    然后在字符串格式语句中使用它

    string.Format("({0}, {1}, '{2}', '{3}')", emailJobId, r.RecipientId, EscapeSQLParamString(r.Name), EscapeSQLParamString(r.EmailAddress))