C# 将blob更新为mysql时在命令执行过程中遇到致命错误
我们使用的是MySql.Data.dll版本6.9.5.0 此操作失败,错误为:在命令执行期间遇到mysql致命错误。你知道为什么会失败吗?Tl;DR 由于分支比较不匹配,您正在使用6个未绑定的变量执行查询,但只绑定了5个参数 细节 堆栈跟踪/异常中没有提供足够的信息来明确回答问题,但似乎猜测上述分支中的错误做法是根本原因,即在这两个分支中:C# 将blob更新为mysql时在命令执行过程中遇到致命错误,c#,mysql,C#,Mysql,我们使用的是MySql.Data.dll版本6.9.5.0 此操作失败,错误为:在命令执行期间遇到mysql致命错误。你知道为什么会失败吗?Tl;DR 由于分支比较不匹配,您正在使用6个未绑定的变量执行查询,但只绑定了5个参数 细节 堆栈跟踪/异常中没有提供足够的信息来明确回答问题,但似乎猜测上述分支中的错误做法是根本原因,即在这两个分支中: String query = ""; string constr = ConfigurationSettings.AppSettings[
String query = "";
string constr = ConfigurationSettings.AppSettings["MySQLConnectionStringForIMS"];
using (MySqlConnection con = new MySqlConnection(constr))
{
//string query = "INSERT INTO user(name, files,contentType) VALUES (@name,@files,@contentType)";
if (update == "mainSec")
{
query = "update main_section set contentType=@contentType,fileData=@fileData,fileNameAfterUploading=@fname,haveDir=@dir where id=@id";
}
else
{
query = "update sub_section set subContentType=@contentType,subFileData=@fileData,fileNameAfterUploading=@fname,haveDir=@dir where MainSecId=@id and id=@subId";
}
using (MySqlCommand cmd = new MySqlCommand(query))
{
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("@contentType", contentType);
cmd.Parameters.AddWithValue("@fileData", data);
cmd.Parameters.AddWithValue("@fname", filename);
cmd.Parameters.AddWithValue("@dir", 1);
cmd.Parameters.AddWithValue("@id", mainId);
if (update == "subSec")
{
cmd.Parameters.AddWithValue("@subId", subId);
}
con.Open();
int st = cmd.ExecuteNonQuery();
if (st == 1)
{
//Uri uri = new Uri(url, UriKind.Absolute);
//System.IO.File.Delete(uri.LocalPath);
}
con.Close();
}
}
及
。。由于update
type/mode字符串未被限制在mainSec
或subSec
的范围内,因此有一个分支使用了带有6个参数标记的子部分
查询,但没有绑定第6个标记,从而导致了错误
在这种情况下,我建议不要使用弱约束字符串,而是严格约束更新
的输入范围,例如使用枚举
:
if (update == "subSec")
{
... bind the 6th parameter here
}
因为只有两种可能的模式,所以可以使用条件赋值避免第一个查询赋值分支,即
enum UpdateMode
{
Invalid = 0, // This will be the default, and can be used to ensure assignment
MainSection,
SubSection
}
这样做的好处是query
的声明和赋值可以绑定在一起(并提供了额外的编译器保证必须赋值query
)
(如果有两个以上的查询(以及两个以上的枚举状态),则静态IReadOnlyDictionary
将允许扩展此模式。)
绑定也将更改为
Contract.Assert(updateMode != UpdateMode.Invalid);
var query = updateMode == UpdateMode.MainSection
? "update main_section set contentType=@contentType ... "
: "update sub_section set subContentType=@contentType ... ";
一些注释
con.Close()不需要code>,因为您已经在
新连接周围使用了
-,
将调用Dispose
。如果它打开,请关闭
- 我知道这已经被注释掉了,但我强烈建议不要在此时使用文件IO
- 从关注点分离的角度来看,删除文件属于其他地方。如果删除仅依赖于正在更新的一行,则可以从此Blob更新方法返回
- I/O将在
块的范围内,这可能会阻碍MySql连接(到连接池)的发布using
- IO可能会失败,并且取决于任何事务控制,这可能会使系统处于有问题的状态,即记录被删除,但文件未被删除
if(update==“subSec”)
更改为if(update!=“mainSec”)
,以确保参数绑定与上面定义的正确查询同步。@StuartLC我可以看出这是问题所在。如果它看到更新!='mainSec”,它将使用subSec查询。但是,如果更新也是!=如果设置为“subSec”,则不会分配“@subId”值,并且会导致致命错误。请按照此页面上的所有说明捕获异常详细信息,包括所有内部异常,然后使用该信息编辑您的问题:谢谢,各位!我找到了问题的根本原因。“更新”的价值是“SubSec”。因此,未正确进行比较。感谢@StuartLC和Ryan GibbsThanks@Stuart分享这些宝贵的编程方法。
Contract.Assert(updateMode != UpdateMode.Invalid);
var query = updateMode == UpdateMode.MainSection
? "update main_section set contentType=@contentType ... "
: "update sub_section set subContentType=@contentType ... ";
if (updateMode == UpdateMode.SubSection)
{
cmd.Parameters.AddWithValue("@subId", subId);
}
if (st == 1)
{
// File.IO
}