子串错误,但不使用子串

时间:2010-10-07 23:24:32

标签: c# .net windows-services string-formatting

我有以下代码:

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服务,可以在远程计算机上运行,​​因此调试它并不容易,我没有良好的开发环境来反映它们。

我之前看到过的错误,但似乎总是出现某种子串操作。文本只是一些基本的东西,一个非常类似于另一个,所以我甚至不明白为什么会导致这个。

关于什么或为什么的任何想法?

编辑:好的,所以我有一个aha时刻,并意识到我可以打印出一个堆栈跟踪这里是我得到的 -

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 个答案:

答案 0 :(得分:2)

你需要消毒主体和身体。例如,如果您的主题

');
,您将遇到麻烦。例如,请参阅herehere

答案 1 :(得分:0)

您可能会发现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上失败:

     

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

     

at System.String.InternalSubStringWithChecks(Int32 startIndex,Int32 length,Boolean   fAlwaysCopy)
  at MySql.Data.MySqlClient.MySqlTokenizer.NextParameter()
  at MySql.Data.MySqlClient.Statement.InternalBindParameters(String sql,

我不清楚这是否是固定的;错误报告含糊不清。您应该至少检查以确保您使用的是最新的MySQL库。

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

答案 2 :(得分:0)

这通常是由包含特殊字符和名称的字符串引起的,通常是罪魁祸首,例如O'Reilly。如果在INSERT ... VALUES语句中有该字符串,则会报告奇怪的错误。还有其他特殊的角色,如&amp;等等。以寻找。

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

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

然后在String格式语句中使用它

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