Значение, не заданное в команде C# SQL

Я написал код, который будет читать в файле txt и анализировать данные и назначать правильные номера в правильные столбцы таблицы SQL. Проблема заключается в том, что я реализовал слияние, чтобы данные из разных строк в txt-файле отображались в разных столбцах, но в одной и той же строке в таблице SQL. Однако теперь я получаю проблему, что моя переменная не устанавливается, но это было до того, как я реализовал слияние. Это мой код:

foreach (var record in records)
{
    Console.WriteLine(record.RESORT);
    Console.WriteLine(record.FORMATTED_AMOUNT);
    // This allows us to split what column a row goes into based on whether it is a day and what SUB_GRP_1 it is
    string Heading = record.HEADING_2;
    string Group = record.SUB_GRP_1;
    string column;
    if (Heading == "DAY" && Group == "OCC_PERC")
    {
        column = "Percent_Rooms_Occupied";
    }
    else if (Heading == "DAY" && Group == "OCC_PERC_WO_CH")
    {
        column = "Percent_Rooms_Occupied_minus_Comp_and_House";
    }
    else if (Heading == "DAY" && Group == "ADR_ROOM")
    {
        column = "ADR";
    }
    else if (Heading == "DAY" && Group == "ADR_ROOM_WO_CH")
    {
        column = "ADR_minus_Comp_and_House";
    }
    else if (Heading == "DAY" && Group == "ROOMREV_AVL_ROOMS_MINUS_OOO")
    {
        column = "Revenue_per_Available_Room_minus_OOO";
    }
    else if (Heading == "DAY" && Group == "TOTAL_REVENUE")
    {
        column = "Total_Revenue";
    }
    else if (Heading == "DAY" && Group == "ROOM_REVENUE")
    {
        column = "Room_Revenue";
    }
    else if (Heading == "DAY" && Group == "FOOD_BEV_REVENUE")
    {
        column = "Food_And_Beverage_Revenue";
    }
    else if (Heading == "DAY" && Group == "OTHER_REVENUE")
    {
        column = "Other_Revenue";

    }
    else if (Heading == "DAY" && Group == "PHYSICAL_ROOMS")
    {
        column = "Total_Rooms_in_Hotel";

    }
    else if (Heading == "DAY" && Group == "OCC_ROOMS")
    {
        column = "Rooms_Occupied";

    }
    else if (Heading == "DAY" && Group == "OCC_MINUS_COMP_HU")
    {
        column = "Rooms_Occupied_minus_Comp_and_House_Use";

    }
    else if (Heading == "DAY" && Group == "COMP_ROOMS")
    {
        column = "Complimentary_Rooms";

    }
    else
    {
        column = "";
    }




    // SQL connection. Creates connection and command and inserts the values taken from the File Helper engine into the SQL table
    SqlCommand cmd;
    SqlConnection conn;


    conn = new SqlConnection("Data Source=hureports01;Initial Catalog=hureports;Integrated Security=True");
    conn.Open();
    var sqlCommand = string.Format(@"MERGE [HEWreport] AS target USING (select @Property_ID as Property_ID, @val as {0}) AS source ON (target.Property_ID = source.Property_ID) WHEN MATCHED THEN UPDATE SET {0}= source.{0}
                                    WHEN NOT MATCHED THEN INSERT (Property_ID, {0}) VALUES (source.Property_ID, source.{0});", column);
    cmd = new SqlCommand(sqlCommand, conn);
    cmd.Parameters.AddWithValue("@Property_ID", record.RESORT);
    cmd.Parameters.AddWithValue("@val", record.FORMATTED_AMOUNT);
    cmd.ExecuteNonQuery();
}

И это ошибка, которую я продолжаю получать:

Необработанное исключение типа ‘ System.Данные.SqlClient.SqlException ‘ произошло в системе.Данные.файл DLL

Дополнительная информация: параметризованный запрос ‘ (@Property_ID nvarchar(5),@val nvarchar (4000))MERGE [HEWreport] ‘ожидает параметр’ @val’, который не был предоставлен.

Я знаю, что это как-то связано с ошибкой в моей линии

cmd.Parameters.AddWithValue("@val", record.FORMATTED_AMOUNT);

Но я не знаю, как это исправить

2 ответа

  1. Вы подключили SQL-профилировщик? Что такое запрос, который отправляется на SQL Server?

    Код (в общем) выглядит правильным.
    Сообщение об ошибке означает, что «@val » не предоставляется, но код, который вы показываете, добавляет его. Это может быть record.FORMATTED_AMOUNTnull или имеет какую-то другую проблему, которая заставляет параметр не добавляться, но это должно вызвать исключение C#.

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

    Если профилировщик SQL не получает необходимую информацию, попробуйте статически указать значения в C# и посмотрите, что произойдет.

    var sqlCommand = @"MERGE [HEWreport] AS target USING (select @Property_ID as Property_ID, @val as ColumnName) AS source ON (target.Property_ID = source.Property_ID) WHEN MATCHED THEN UPDATE SET ColumnName = source.ColumnName
                                    WHEN NOT MATCHED THEN INSERT (Property_ID, ColumnName) VALUES (source.Property_ID, source.ColumnName);";
    cmd = new SqlCommand(sqlCommand, conn);
    cmd.Parameters.AddWithValue("@Property_ID", "215");
    cmd.Parameters.AddWithValue("@val", "17");
    cmd.ExecuteNonQuery();
    

    прочие комментарии:

    Слияние является избыточным для инструкции insert (без обновления или удаления). Вместо этого используйте что-то вроде:

    IF EXISTS (SELECT * FROM [HEWreport] WHERE Property_ID = @Property_ID)
        INSERT INTO [HEWreport] (Property_ID, <ColumnName>) VALUES (@Property_ID, @val);
    

    Как было указано в комментариях, cmd.Parameters.AddWithValueне рекомендуется. Вместо этого создайте SqlParmeter:

    cmd.Parameters.Add(new SqlParameter("@Property_ID", SqlDbType.Int) { Value = record.RESORT});
    cmd.Parameters.Add(new SqlParameter("@val", SqlDbType.NVarChar, 250) { Value = record.FORMATTED_AMOUNT});
    

    Документация:
    Конструктор SqlParameter (String, SqlDbType)
    Конструктор SqlParameter (String, SqlDbType, Int32)