MySQL 连接器/NET 的 MySqlCommand 不使用参数
Posted
技术标签:
【中文标题】MySQL 连接器/NET 的 MySqlCommand 不使用参数【英文标题】:MySQL Connector/NET's MySqlCommand not using Parameters 【发布时间】:2014-07-04 16:49:53 【问题描述】:所以我在使用 mysql 连接器时遇到了一些问题(特别是针对 .NET)。通常,我不会使用参数化——尽管我意识到这样做会使我的程序容易受到 SQL 注入的影响。
不幸的是,我不能这样做。我需要将一个字节数组(这些字节来自于在该程序的客户端读取图像文件)存储到 MySQL 数据库中。显然,将字节数组放入查询字符串是行不通的。这只会将“System.Byte[]
”放入数组中。
我以前使用过参数化查询——但仅限于java。以下是我的代码,其中packet
是一个我保证在所有情况下都会返回正确数据的对象(出于测试目的,我什至添加了一个包含所有硬编码数据的驱动程序类)和Server
保证单例的连接是开放有效的。
MySqlCommand cmd = new MySqlCommand("insert into `screenshots` (`playerId`, `serverId`, `data`, `uploadDate`, `uploadingUserId`) values(?playerId, ?serverId, \"?attachmentData\", \"?dateTime\", ?userId,)", Server.getSingleton().getDbManager().getConnection());
cmd.Parameters.AddWithValue("?playerId", packet.getPlayerId()); //string of an integer
cmd.Parameters.AddWithValue("?serverId", packet.getServerId()); //string of an integer
cmd.Parameters.AddWithValue("?attachmentData", packet.getAttachmentData()); //byte[]
cmd.Parameters.AddWithValue("?dateTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
cmd.Parameters.AddWithValue("?userId", packet.getUserId()); //string of an integer
cmd.executeNonQuery();
我遇到的问题是 MySql 连接器/NET 似乎永远不会用它们的值替换参数。我试过实例化一个new MySqlParameter
对象,设置它的Value
,然后调用cmd.Parameters.Add(...)
,但这会出现同样的问题。
我查看了 MySQL 文档,它说要使用 MySqlCommmand#Parameters.AddWithValue(string, object)
,并且我没有遗漏其他步骤。
每当我将 Visual Studio 的调试器附加到进程时,可以看到参数已全部添加到 Parameters
列表属性中;但是,当查询执行时,即时调试器会停止执行并突出显示带有cmd.executeNonQuery()
的行,表示'?dateTime' is not a valid value for column 'dateTime'
(其中dateTime
列的SQL 类型为DateTime
)或其他内容那种程度。
这显然意味着参数没有被它们的值替换。 ?dateTime
不是DateTime
字段的有效值,因为它必须采用yyyy-MM-dd HH:mm:ss
的格式,因此连接器会引发异常。但是我做错了什么?
提前感谢您的帮助——我习惯于用 Java 做与数据库相关的事情(以及套接字逻辑等),但这是一个学校项目,需要用 C# 完成。
【问题讨论】:
【参考方案1】:那些看起来不像是有效的 MySQL 参数;如果您想要命名参数,请使用@yournamehere
,如下所示:
MySqlCommand cmd = new MySqlCommand("insert into `screenshots` (`playerId`, `serverId`, `data`, `uploadDate`, `uploadingUserId`) values(@playerId, @serverId, @attachmentData, @dateTime, @userId)", Server.getSingleton().getDbManager().getConnection());
cmd.Parameters.AddWithValue("@playerId", packet.getPlayerId());
你也不应该引用参数; ADO.NET 将根据目标列的数据类型在必要时执行此操作。
来源:http://dev.mysql.com/doc/connector-net/en/connector-net-tutorials-parameters.html
【讨论】:
根据你对 MySQL 的引用,它似乎已经过时了——我实际上是自己阅读了那个页面;但是,我还遇到了 MySQL Connector/NET 的某个版本的发行说明,它指出@
已更改为 ?
以支持用户(例如,user@localhost
将无效,因为它会尝试找到一个参数)。当然,有一种方法可以使用连接字符串选项将参数改回@
。但是,我将研究引用参数。
呃,我为不尝试删除引号而感到非常愚蠢——我认为 C# 对我不会那么好。删除它们有效,但参数使用?
转义。谢谢!
@DanJesensky 嗯。文档说“此选项在 Connector/Net 5.2.2 中已弃用。现在所有代码都应使用 '@' 符号作为参数标记来编写。” - 您使用的是什么版本的连接器?
我不确定我在哪里读到它了,但我记得在 *** 上看到一堆问题,使用 ?
而不是 @
。我将编辑我的代码以改用@
。再次感谢。以上是关于MySQL 连接器/NET 的 MySqlCommand 不使用参数的主要内容,如果未能解决你的问题,请参考以下文章