Попытка использовать «Scope_Identify ()» в хранимой процедуре из метода в классе C#, чтобы получить идентификатор результирующей вставки - PullRequest
2 голосов
/ 28 января 2020

У меня есть хранимая процедура для вставки записи в таблицу. Я пытаюсь использовать Scope_Identity(), чтобы вернуть созданное значение идентификатора. Я вызываю процедуру из метода с именем Add_Claimant(). Метод вставляет заявителя в таблицу нормально, но я не получаю обратно идентификатор.

Чтобы это работало, я добавил @ID int output в список параметров для хранимых процедур. После VALUES части оператора Insert я также добавил 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);
    }
}

Ответы [ 2 ]

1 голос
/ 28 января 2020

Не делайте этого:

id = cmd.Parameters["@ID"].Value.ToString();
this.ClmntTbl_ID = Convert.ToInt32(id);

Из-за проблем локализации / культуры преобразования между строками и числами или строками и датами являются удивительно дорогими операциями для компьютеров. Более того, они также являются источником ошибок. Это то, что вы хотите минимизировать и избегать, когда можете. @ID значение параметра уже является целым числом, поэтому при окончательном назначении можно пропустить преобразование в строку и обратно и выглядеть примерно так:

this.ClmntTbl_ID = (int)cmd.Parameters["@ID"].Value;

Но это предполагает, что вы на самом деле есть значение там. Вам все еще нужно учитывать, когда @ID равно NULL. Это проблема из оригинального кода. Если @ID равно нулю, вызов .ToString() приводит к пустой строке, которая соответствует значению, которое вы нашли, когда увидели сообщение об ошибке. Итак, давайте добавим нулевую проверку:

var result = cmd.Parameters["@ID"].Value;
if (! DBNull.Value.Equals(result))
    this.ClmntTbl_ID = (int)result;

Что вы хотите сделать в случае неудачной проверки, решать вам. Но, вероятно, вы хотите исправить хранимую процедуру, чтобы выяснить, почему она генерирует NULL здесь, в первую очередь.

0 голосов
/ 28 января 2020

Это было исправлено. В моем списке параметров я передал:

SqlCommand cmd = connection.CreateCommand ();

cmd.CommandText = "Execute ADD_CLAIMANT_PO C" + Param_String;

У меня должен был быть @ID OUTPUT вместо @ID.

Есть еще один лучший способ сделать это, и я приму этот метод, но у меня уже не 11 лет современного программирования (я был на мейнфрейме), и я только учусь C# загрузки.

Таким образом, я уверен, что у меня есть много «лучших практик», которые нужно выучить.

Спасибо всем, кто помог.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...