我有一些看起来像这样的代码(我将其简化为专注于该问题,但是该代码与下面的代码完全相同,但替换了敏感的数据名称):
private const string TargetIdParamName = "TargetId";
private const string LinkedGroupIdParamName = "LinkedGroupId";
private static readonly string UpdateLinkFromSql =
$@"UPDATE MyTableName
Set LinkFromId = :{LinkedGroupIdParamName}
WHERE Id = :{TargetIdParamName}";
using (var dbConn = GetConnection())
{
dbConn.Open();
using (var trans = dbConn.BeginTransaction())
{
try
{
var cmd = dbConn.CreateTransactedCommand(trans);
AddParameters(cmd);
cmd.CommandText = UpdateLinkFromSql;
cmd.Parameters[TargetIdParamName].Value = request.TargetGroupId;
cmd.Parameters[LinkedGroupIdParamName].Value = request.BreakPreviousLink ? DBNull.Value : (object) request.PreviousGroupId.Value;
cmd.ExecuteNonQuery();
trans.Commit();
}
catch (Exception e)
{
trans.Rollback();
throw;
}
}
}
private void AddParameters(OracleCommand cmd)
{
cmd.Parameters.Add(TargetIdParamName, OracleDbType.Long, ParameterDirection.Input);
cmd.Parameters.Add(LinkedGroupIdParamName, OracleDbType.Long, ParameterDirection.Input);
}
public static class DataAccessExtensions
{
public static OracleCommand CreateTransactedCommand(this OracleConnection source, OracleTransaction trans)
{
var cmd = source.CreateCommand();
cmd.Transaction = trans;
return cmd;
}
}
为了说明问题,可以说'TargetGroupId'为12345,'PreviousGroupId'为67890。
根据此代码,我希望ID为12345的记录的LinkFromId更新为67890。
但是发生了相反的情况,ID为67890的记录的LinkFromId设置为12345。
现在轻松获得预期的行为,交换分配给每个参数的值。
但是问题仍然存在,为什么参数要与期望值互换?是的,我已经三重检查了查询是否符合我的想法,参数是否正确传递(就像我没有意外地以相反的顺序或其他任何方式命名查询中的参数)。我想念什么吗?
确保在执行命令之前告诉命令对象按名称绑定参数。
cmd.BindByName = true;
如果您不这样做,通常会绑定它们。如果以与您引用它们相反的顺序添加它们,那将说明交换。
我总是将该属性设置为true
,因为替代方法不太可用。它应该是默认值,但这将是一个重大更改。幸运的是,它特定于Oracle提供程序。