Ошибка подстроки, хотя не используется подстрока - PullRequest
0 голосов
/ 08 октября 2010

У меня есть следующий код:

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 ]

2 голосов
/ 08 октября 2010

Вам нужно продезинфицировать субъект и тело. Например, если ваш субъект

');
, у вас возникнут проблемы. См. Например здесь и здесь .
0 голосов
/ 08 октября 2010

Обычно это вызвано тем, что ваша строка содержит специальный символ, а имя часто является виновником, как, например, 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))
0 голосов
/ 08 октября 2010

Вы можете найти этот отчет об ошибках MySQL интересно:

Строка 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 */

обратная косая черта в строке - исключение возврата соединителя
работает в браузере запросов / CLI / соединителе 5.x, ошибка 6.0.3:

Индекс и длина должны указывать на местоположение в строке.
Имя параметра: длина

в System.String.InternalSubStringWithChecks (Int32 startIndex, Int32 длина, логическое значение fAlwaysCopy)
в MySql.Data.MySqlClient.MySqlTokenizer.NextParameter ()
в MySql.Data.MySqlClient.Statement.InternalBindParameters (String sql,

Мне не ясно, исправлено ли это каждыйОтчет об ошибках неоднозначен. Вы должны хотя бы проверить, используете ли вы последние версии MySQL.

Возможно, поиграйте с любыми строками, содержащими обратную косую черту - посмотрите, можете ли вы изолировать данные проблемы.

...