2010-10-07 11 views
0

substring Je le code suivant:erreur Substring mais pas en utilisant

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, 
          "[email protected]", 
          "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; 
     } 

Ce code fonctionne bien lors de l'exécution d'une tâche, mais j'exécuter ce même code pour une autre tâche et il ne fonctionne pas. Il me donne l'erreur suivante:

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

Maintenant, la seule différence entre chaque fois que je le lance est le sujet et le corps du message. Ils sont stockés dans un fichier de ressources et transmis lorsque la méthode est appelée. Mais ce que je n'arrive pas à comprendre, c'est où cette exception arriverait-elle? Il s'agit d'un service Windows et fonctionne sur une machine distante, donc le débogage n'est pas si simple et je n'ai pas un bon environnement de développement pour refléter le leur.

L'erreur que j'ai déjà vue mais qui semble toujours être liée à une sorte de manipulation de sous-chaîne. Le texte est juste quelques trucs de base et l'un est très similaire à l'autre, donc je ne peux même pas voir pourquoi cela causerait cela.

Des idées sur quoi ou pourquoi?

EDIT: Ok, donc après avoir eu un moment aha et réalisé que je pouvais imprimer une trace de la pile ici est ce que je suis -

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 

Ce que je ne suis pas familier avec autant est des déclarations préparées pour MySql . Je n'essaie pas d'utiliser quelque chose comme ça. Mais j'ai des guillemets simples dans le texte. Mais j'ai ceux dans les deux textes et ils fonctionnent bien dans le premier, donc je ne sais pas si c'est ça. Je leur échappe dans le fichier de ressources en utilisant backslash.

+1

Avez-vous une trace complète de la pile? – adrianbanks

+0

Pour une raison quelconque, il m'est tout simplement venu à l'esprit de l'imprimer. Je travaille donc sur la mise en place du code pour le faire maintenant. Donne moi 5 minutes. – spinon

Répondre

2

Vous devez désinfecter le sujet et le corps. Par exemple, si votre sujet est

');
, vous aurez des problèmes. Voir par exemple here et here.

+0

Je ne sais pas si cela va résoudre le problème de l'OP, mais spinon, votre code est ** très très ** vulnérable à l'injection SQL. Ce ne devrait pas être malveillant. –

+0

@Michael Je me rends compte que, mais c'est juste un service Windows interne que je cours sur des données contrôlées. Il n'aurait jamais à s'inquiéter à moins que quelqu'un ne soit entré dans la machine où le service fonctionne. Et si cela arrivait, j'aurais d'autres problèmes à régler. Mais merci de mentionner de toute façon. – spinon

+0

@spinon: donc, vous pouvez garantir que le sujet et le corps ne contiendront jamais de caractère '' ''? Vous n'avez jamais un O'Brien dans votre entreprise? Je ne veux pas vous hectoriser, mais le coût d'utilisation des paramètres est si bas, comparé aux chances que, à un moment donné, vous rencontriez des problèmes. –

0

Vous trouverez peut-être this MySQL bug report intéressante:

SQL string with escaped backslash inside.

examples:

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 */

backslash in string - connector return exeption
works on Query Browser/CLI/connector 5.x, fail on 6.0.3:

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

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

Il est pas clair pour moi si cela était tout fixe; le rapport de bug est ambigu. Vous devriez au moins vérifier pour vous assurer que vous utilisez les dernières bibliothèques MySQL, cependant. Peut-être jouer avec des chaînes contenant des barres obliques inverses - voir si vous pouvez isoler les données de problème.

0

Ceci est généralement causé par votre chaîne contenant un caractère spécial et le nom est souvent le coupable, à titre d'exemple O'Reilly. Si vous avez cette chaîne dans votre instruction INSERT ... VALUES, vous obtiendrez des erreurs étranges signalées. Il y a aussi d'autres caractères spéciaux comme & et etc. à surveiller.

Deux suggestions pour résoudre votre problème: - paramètre Utiliser la liaison plutôt que de construire votre propre chaîne SQL - Mais si vous devez utiliser ce qui précède, essayez d'écrire une petite routine qui a échappé automatiquement la chaîne avant d'être utilisé dans le paramètre. par exemple.

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

puis utilisez dans votre déclaration de format de chaîne

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