Должен объявлять скалярную переменную при передаче bool - PullRequest
0 голосов
/ 04 июня 2019

SQL Server - 2014. Visual Studio 2017.

Я пытаюсь передать 3 параметра в SQL Server, но получаю эту ошибку:

System.Data.SqlClient.SqlException: 'Должен объявить скалярную переменную "@ Title1Item".'

Я включил код на стороне C # и SQL Server. Может кто-нибудь сказать мне, что я делаю не так?

public DataTable GetInventoryByAssetDescription (string Desc, string DispositionText, bool Title1Item) {

    DataTable myRecords = new DataTable(); 
    using (SqlConnection cn = new SqlConnection (ConnectionString)) {

    // Specify which stored procedure to use and add a parameter.
    SqlCommand cmd = new SqlCommand ("GetInventoryByAssetDescription", cn);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue ("@SearchString", Desc);
    cmd.Parameters.AddWithValue ("@DispositionText", DispositionText);
    cmd.Parameters.AddWithValue ("@Title1Item", Title1Item);

    SqlDataAdapter da = new SqlDataAdapter (cmd);
    cn.Open();
    da.Fill (myRecords);
}

ALTER PROCEDURE [dbo].[GetInventoryByAssetDescription] (
    @SearchString varchar(30),
    @DispositionText varchar(200),
    @Title1Item bit
)

Я ожидаю, что 3 параметра будут переданы в хранимую процедуру, но я получаю эту ошибку в строке da.fill (myRecords):

System.Data.SqlClient.SqlException: 'Необходимо объявить скалярную переменную "@ Title1Item".'

РЕДАКТИРОВАТЬ: Простите, ребята. Ржавый старый программист здесь. Код хранимой процедуры:

USE [Inventory]
GO
/****** Object:  StoredProcedure [dbo].[GetInventoryByAssetDescription]    Script Date: 6/4/2019 8:30:15 AM ******/
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
ALTER PROCEDURE [dbo].[GetInventoryByAssetDescription]
      (
            @SearchString varchar(30),
            @DispositionText varchar(200),
            @Title1Item bit
      )  
AS
begin
    SET NOCOUNT ON
    declare @sql nvarchar (2000)

    select @SearchString=UPPER(@SearchString)
    set @sql = '   select in_eq_ID,
        in_eq_TagNumber as TagNumber,
        Title1Item,
        in_eq_AssetDescription as Description,
        in_eq_ExtendedDescription as ExtendedDescription,
        in_eq_SerialNumber as SerialNumber,
        in_eq_ValuationAmount as TotalValue,
        in_eq_CustodianName as Name,
        in_eq_ComplexBuilding as ShortLocation,
        in_eq_SubLocationCode as ShortRoomNumber,
        in_ca_Categories.in_ca_CategoryName as CategoryName,
        in_eq_DispositionDate as DispositionDate,
        DATEADD (dd, 0, DATEDIFF (dd, 0, in_eq_Equipment.in_eq_AcquisitionDate)) as AcquisitionDate
        from in_eq_Equipment
            LEFT JOIN in_ca_Categories ON in_eq_Equipment.in_eq_CategoryID_fk = in_ca_Categories.in_ca_CategoryID
            where @Title1Item = Title1Item
                AND upper (in_eq_AssetDescription) LIKE upper ('''+ @SearchString + ''')'

        set  @sql=@sql+'   ' + ISNULL(@DispositionText,' ')  + '  order by in_eq_AssetDescription'
        execute (@sql)
        return
end

Ответы [ 3 ]

0 голосов
/ 04 июня 2019

Когда вы используете тип данных BIT в SQLServer в качестве параметра SP, из C # вы должны отправлять значения 1 или 0 не true или false, поэтому вам нужно преобразовать bool в int (1 для true и 0 для false)

Например

cmd.Parameters.AddWithValue ("@Title1Item", Title1Item ? 1 : 0);

или

cmd.Parameters.AddWithValue ("@Title1Item", (int)Title1Item);
0 голосов
/ 04 июня 2019

справа; проблема в вашем SP, а не в коде C #. Это не может работать так, как написано. Параметры и локальные переменные не являются «окружающими» - они не будут определены внутри блока EXEC или EXECUTE, поскольку они там не ограничены. В некоторых случаях есть sp_executesql, который позволяет передавать параметры / значения, объявляя их и добавляя их в качестве дополнительных параметров, но в вашем случае это не будет хорошей идеей потому что по сути вы делаете что-то невероятно опасное, то есть объединяете входные данные для создания SQL. Ваша хранимая процедура прямо сейчас является дырой для внедрения SQL и может быть использована для захвата вашего сервера с минимальными усилиями. Если вы согласны с тем, что ваши данные украдены и ваша база данных уничтожена, вы можете встроить / объединить @Title1Item точно так же, как вы это сделали с другими, но: это - ужасная идея , и она вас навредит.

0 голосов
/ 04 июня 2019

Вы можете добавить тип к параметру

 cmd.Parameters.Add("@Title1Item", SqlDbType.Bit).Value =
 Title1Item;

Также хранимая процедура не возвращает результат, но ваш SP есть. Это не очень хорошая практика - вы не можете создать Datacontext в этом случае (EF всегда генерирует результат возврата int для SP), снижается производительность вашего выполнения и создается плохо поддерживаемый неясный код. Но никто не запрещает тебе за это. О вашем определении SP: where @Title1Item = Title1Item должно быть похоже на where' + @Title1Item + ' = Title1Item

...