我有一个用于在表中插入记录的存储过程。我正在尝试使用Scope_Identity()
来取回创建的 ID 值。我从名为Add_Claimant()
的方法调用该过程。该方法将索赔人插入表中,但我没有取回 ID。
为此,我向存储过程的参数列表中添加了@ID int output
。在插入语句的VALUES
部分之后,我还添加了SET @ID=SCOPE_IDENTITY()
.然后在我的方法中,我添加了@ID
参数,如下所示:
cmd.Parameters.Add("@ID", SqlDbType.Int).Direction = ParameterDirection.Output;
我打开连接并正常执行存储过程,然后像这样检索参数值:
connection.Open();
cmd.ExecuteNonQuery();
String id = cmd.Parameters["@ID"].Value.ToString();
this.ClmntTbl_ID = Convert.ToInt32(id);
此时,我希望看到ClmntTbl_ID
成员中输出参数的实际值。但是,我得到以下异常:
System.FormatException:"输入字符串的格式不正确。
如果我将鼠标悬停在id
它会显示其值为"(空字符串(。
我错过了什么?
这是完整的方法。
//Connection that is passed from the calling program.
SqlConnection My_Connection = new SqlConnection(ConnectionString);
public void Add_Claimant(SqlConnection connection)
{
string id;
// Build the parameter string to pass to the stored procedure.
String Param_String;
Param_String = "@SSN, @LEGACYID, @FIRSTNAME, @LASTNAME, @MIDDLEI, @HOMEPHONE, @CELLPHONE, @BIRTHDATE";
Param_String = Param_String + ", @SEX, @RACECODE, @ETHNICCODE, @MARITALSTATUS, @EDULEVEL, @CITIZENCODE";
Param_String = Param_String + ", @LEGACYPIN, @PASSWORDVALUE, @HANDCAP_IND, @LATEST_RTWDATE, @LATEST_RECALLTWDATE";
Param_String = Param_String + ", @LATEST_NEWHIRE_EMP_ACCT, @LATEST_NEWHIREDATE, @DECEASED_IND, @ALIENREG_NUM, @ALIENREG_EXPDATE, @PAYMETHOD, @ID";
SqlCommand cmd = connection.CreateCommand();
cmd.CommandText = "Execute ADD_CLAIMANT_POC " + Param_String; //Call the stored procedure ADD_CLAIMANT_POC
cmd.Parameters.Add("@SSN", SqlDbType.VarChar, 9).Value = this.ClmntTbl_SSN;
cmd.Parameters.Add("@LEGACYID", SqlDbType.VarChar, 9).Value = this.ClmntTbl_LEGACYCID;
cmd.Parameters.Add("@FIRSTNAME", SqlDbType.VarChar, 50).Value = this.ClmntTbl_FIRSTNAME;
cmd.Parameters.Add("@LASTNAME", SqlDbType.VarChar, 50).Value = this.ClmntTbl_LASTNAME;
cmd.Parameters.Add("@MIDDLEI", SqlDbType.VarChar, 1).Value = this.ClmntTbl_MIDDLEI;
cmd.Parameters.Add("@HOMEPHONE", SqlDbType.VarChar, 10).Value = this.ClmntTbl_HOMEPHONE;
cmd.Parameters.Add("@CELLPHONE", SqlDbType.VarChar, 10).Value = this.ClmntTbl_CELLPHONE;
cmd.Parameters.Add("@BIRTHDATE", SqlDbType.DateTime).Value = this.ClmntTbl_BIRTHDATE;
cmd.Parameters.Add("@SEX", SqlDbType.Char, 1).Value = this.ClmntTbl_SEX;
cmd.Parameters.Add("@RACECODE", SqlDbType.Char, 1).Value = this.ClmntTbl_RACECODE;
cmd.Parameters.Add("@ETHNICCODE", SqlDbType.Char, 1).Value = this.ClmntTbl_ETHNICCODE;
cmd.Parameters.Add("@MARITALSTATUS", SqlDbType.Char, 1).Value = this.ClmntTbl_MARITALSTATUS;
cmd.Parameters.Add("@EDULEVEL", SqlDbType.Int).Value = this.ClmntTbl_EDULEVEL;
cmd.Parameters.Add("@CITIZENCODE", SqlDbType.Char, 1).Value = this.ClmntTbl_CITIZENCODE;
cmd.Parameters.Add("@LEGACYPIN", SqlDbType.Int).Value = this.ClmntTbl_LEGACYPIN;
cmd.Parameters.Add("@PASSWORDVALUE", SqlDbType.VarChar, 50).Value = this.ClmntTbl_PASSWORDVALUE;
cmd.Parameters.Add("@HANDCAP_IND", SqlDbType.Char, 1).Value = this.ClmntTbl_HANDICAP_IND;
cmd.Parameters.Add("@LATEST_RTWDATE", SqlDbType.DateTime).Value = this.ClmntTbl_LATEST_RTWDATE;
cmd.Parameters.Add("@LATEST_RECALLTWDATE", SqlDbType.DateTime).Value = this.ClmntTbl_LATEST_RECALLTWDATE;
cmd.Parameters.Add("@LATEST_NEWHIRE_EMP_ACCT", SqlDbType.VarChar, 18).Value = this.ClmntTbl_LATEST_NEWHIRE_EMP_ACCT;
cmd.Parameters.Add("@LATEST_NEWHIREDATE", SqlDbType.DateTime).Value = this.ClmntTbl_LATEST_NEWHIREDATE;
cmd.Parameters.Add("@DECEASED_IND", SqlDbType.Char, 1).Value = this.ClmntTbl_DECEASED_IND;
cmd.Parameters.Add("@ALIENREG_NUM", SqlDbType.VarChar, 9).Value = this.ClmntTbl_ALIENREG_NUM;
cmd.Parameters.Add("@ALIENREG_EXPDATE", SqlDbType.DateTime).Value = this.ClmntTbl_ALIENREG_EXPDATE;
cmd.Parameters.Add("@PAYMETHOD", SqlDbType.Char, 1).Value = this.ClmntTbl_PAYMETHOD;
cmd.Parameters.Add("@ID", SqlDbType.Int).Direction = ParameterDirection.Output;
if (connection != null && connection.State == ConnectionState.Closed)
{
connection.Open(); //if it was not opened in the calling program, or if something strange happened and it was closed open the connection.
cmd.ExecuteNonQuery(); //Execute stored procedure.
id = cmd.Parameters["@ID"].Value.ToString();
this.ClmntTbl_ID = Convert.ToInt32(id);
connection.Close();
// assuming that if I open it (becuase it wasn't open already) then I should close. This may not be correct. Will have to investigate.
}
else
{
cmd.ExecuteNonQuery(); // If it's already open, then control for that portion of the processess is in the code calling this method so just execute the query.
id = cmd.Parameters["@ID"].Value.ToString();
this.ClmntTbl_ID = Convert.ToInt32(id);
}
}
不要这样做:
id = cmd.Parameters["@ID"].Value.ToString();
this.ClmntTbl_ID = Convert.ToInt32(id);
由于本地化/区域性问题,字符串和数字或字符串和日期之间的转换对于计算机来说是非常昂贵的操作。此外,它们也往往是错误的来源。它们是您希望尽可能减少和避免的事情。@ID
参数值已经是一个整数,因此最终赋值可以跳过转换为字符串并再次转换回来,看起来更像这样:
this.ClmntTbl_ID = (int)cmd.Parameters["@ID"].Value;
但这假设你实际上有一个价值。您仍然需要考虑何时NULL
@ID
。这是原始代码的问题。如果@ID
为 null,则调用.ToString()
将生成一个空字符串,该字符串与看到错误消息时找到的值匹配。因此,让我们添加一个空检查:
var result = cmd.Parameters["@ID"].Value;
if (! DBNull.Value.Equals(result))
this.ClmntTbl_ID = (int)result;
如果检查失败,您想做什么取决于您。但您可能希望修复存储过程,以找出它首先在此处产生NULL
的原因。
它是固定的。在我的参数列表中,我传递给:
SqlCommand cmd = 连接。创建命令((;
cmd.CommandText = "Execute ADD_CLAIMANT_POC " + Param_String;
我应该有@ID输出而不是@ID。
还有另一种更好的方法可以做到这一点,我将采用这种方法,但我已经离开现代编程大约 11 年了(一直在大型机上(,并且只是在学习 C# 来启动。
因此,我相信我有很多"最佳实践"需要学习。
感谢所有帮助过的人。