Вернуть только что созданную хранимую процедуру C# - PullRequest
0 голосов
/ 25 апреля 2020

Я пытался решить эту проблему безуспешно. Я посмотрел на следующие ссылки здесь , здесь и здесь , но я получаю

Ссылка на объект не установлена ​​в экземпляр объекта.

или

В процедуре или функции InsertHero указано слишком много аргументов.

Когда я выполняю хранимую процедуру в SSMS мои идентификаторы также отключаются в том смысле, что они увеличиваются с 1110 вместо исходного числа, установленного на 100 (это может быть другой проблемой).

Похоже, я на 99% пути и мне не хватает небольшого куска. Чего мне не хватает?

C#:

using (SqlConnection connection = new SqlConnection(ConnectionString))
{
    connection.Open();

    using (SqlCommand command = new SqlCommand("InsertHero", connection))
    {
        command.CommandType = CommandType.StoredProcedure;

        command.Parameters.AddWithValue("@Name", hero.Name);
        command.Parameters.AddWithValue("@Universe", hero.Universe);
        // command.Parameters.Add("@Created_Id", SqlDbType.Int).Direction = ParameterDirection.Output;

        int id = (int)command.ExecuteScalar();
    }
}

Хранимая процедура:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[InsertHero] 
    @Name nvarchar(50), 
    @Universe nvarchar(15), 
    @Created_Id int OUTPUT
AS
    INSERT INTO Hero
    VALUES (@Name, @Universe);

    SET @Created_Id = SCOPE_IDENTITY()
GO

Хранимая процедура (другим способом):

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[InsertHero] 
    @Name nvarchar(50), 
    @Universe nvarchar(15) OUTPUT
AS
    INSERT INTO Hero
    OUTPUT inserted.Id
    VALUES (@Name, @Universe);
GO

РЕДАКТИРОВАТЬ:

Оставьте это здесь на случай, если кто-то наткнется на него. Оказалось, проблема со строкой подключения, поэтому обязательно удвойте и, возможно, сделайте тройную проверку

1 Ответ

2 голосов
/ 25 апреля 2020

Нет необходимости в параметре @CreatedID в первом примере. Просто измените вашу хранимую процедуру на

ALTER procedure [dbo].[InsertHero] @Name nvarchar(50), @Universe nvarchar(15)
as
   Insert into Hero  values (@Name, @Universe);
   SELECT SCOPE_IDENTITY()

Когда вы вызываете ExecuteScalar, результат ожидается как возвращение из оператора SELECT, а не из выходного параметра. Если вы хотите использовать выходной параметр, вам нужно добавить его в коллекцию параметров SqlCommand и прочитать его значение из той же коллекции после выполнения команды.

Также не используйте AddWithValue, этот метод удобен имеет многочисленные недостатки, задокументированные в Можем ли мы прекратить использовать AddWithValue уже , а также в Как код доступа к данным влияет на производительность базы данных

Вместо этого используйте Добавить, указав тип и размер двух параметров

using (SqlConnection connection = new SqlConnection(ConnectionString))
{
    connection.Open();
    using (SqlCommand command = new SqlCommand("InsertHero", connection))
    {
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.Add("@Name", SqlDbType.NVarChar, 50).Value = hero.Name;
        command.Parameters.Add("@Universe", SqlDbType.NVarChar, 15).Value = hero.Universe;
        int id = (int)command.ExecuteScalar();
    }
}

Второй метод также должен работать, если вы вернете обратно параметр @Universe в то же определение, что и в первом примере (предложение No output).

ALTER procedure [dbo].[InsertHero] @Name nvarchar(50), @Universe nvarchar(15)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...