尽管不使用子字符串,但出现子字符串错误

发布于 2024-09-26 06:19:51 字数 3973 浏览 0 评论 0原文

我有以下代码:

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;
        }

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

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 的准备语句。我并不想使用类似的东西。但我在文本中确实有单引号。但我在两篇文章中都有这些内容,而且它们在第一篇中工作得很好,所以不确定是否就是这样。我使用反斜杠在资源文件中转义它们。

I have the following code:

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;
        }

This code runs fine when running for one task but then I run this same code for another task and it doesn't work. It gives me the following error:

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

Now the only difference between each time I run it is the subject and the body of the message. They are stored in a resource file and passed in when the method is called. But what I can't seem to figure out is where would this exception even be happening. It is a windows service and runs on a remote machine so debugging it is not that easy and I don't have a good dev environment to mirror theirs.

The error I have seen before but it always seems to be with some sort of substring manipulation. The text is just some basic stuff and one is very similar to the other so I can't even see why that would be causing this.

Any ideas on what or why?

EDIT: Ok so after I had an aha moment and realized that I could print out a stack trace here is what I got -

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 

What I am not familiar with as much is prepared statements for MySql. I am not trying to use anything like that. But I do have single quotes in the text. But I have those in both texts and they work fine in the first so not sure if that is it. I escape them in the resource file using backslash.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

终难遇 2024-10-03 06:19:51

您需要对对象和身体进行消毒。例如,如果您的主题是

');

you'll run into trouble. See for example here and here.

You need to sanitize the subject and body. For example if your subject is

');

you'll run into trouble. See for example here and here.

牛↙奶布丁 2024-10-03 06:19:51

您可能会发现此 MySQL 错误报告很有趣:

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

示例:

插入 pb_im 设置 m_from=1, m_to=1, m_content='\\=';
插入 pb_im 设置 m_from=1, m_to=1, m_content='\\'; /* 有时有效,
有时会失败*/

字符串中的反斜杠 - 连接器返回异常
适用于查询浏览器/CLI/连接器 5.x,在 6.0.3 上失败:

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

at System.String.InternalSubStringWithChecks(Int32 startIndex, Int32 长度, 布尔值
fAlwaysCopy)
在 MySql.Data.MySqlClient.MySqlTokenizer.NextParameter()
在MySql.Data.MySqlClient.Statement.InternalBindParameters(字符串sql,

我不清楚这是否已全部修复;错误报告不明确。不过,您至少应该检查以确保使用最新的 MySQL 库。

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

You may find this MySQL bug report interesting:

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,

It's not clear to me if this was every fixed; the bug report is ambiguous. You should at least check to make sure you're using the latest MySQL libs, though.

Maybe play with any strings containing backslashes - see if you can isolate the problem data.

冷夜 2024-10-03 06:19:51

这通常是由包含特殊字符的字符串引起的,而名称通常是罪魁祸首,例如 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))

This is usually caused by your string containing special character and name is often the culprit, as an example O'Reilly. If you have that string in your INSERT...VALUES statement, then you will get strange errors reported. There are also other special character like & and etc. to look out for.

Two suggestion to resolve your problem:
- Use parameter binding rather than building your own SQL string
- But if you have to use the above, try write a small routine that automatically escaped the string prior to be used in the parameter. eg.

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

then use it in your String format statement

string.Format("({0}, {1}, '{2}', '{3}')", emailJobId, r.RecipientId, EscapeSQLParamString(r.Name), EscapeSQLParamString(r.EmailAddress))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文