При использовании ExecuteScalar пишет 2 записи вместо одной

Мне нужно знать, какой номер заказа был записан в базу данных. Для этого я использую выражение SQL EXECUTESCALAR.

Я отлаживал программу и следил за базой данных. Запись записывается один раз в базу данных, когда я выполняю вторую команду, она записывает ту же запись во второй раз. Можете ли вы помочь мне, что мне нужно изменить, чтобы он не записывал 2 записи, и я получил свой номер заказа обратно?

Это мой код:

public static int CreateDocumentNumber(string userId, string todaysDate, decimal docprice, decimal docpaid, int packageId, int orderstatus)
{
    int orderId = 0;   //return value order Id

    //create order 
    string connectionString = ConfigurationManager.ConnectionStrings["conString"].ConnectionString;
    string insertSql = "INSERT INTO [dbo].[LD_Orders](TD_OrdUserID, TD_OrdDate, TD_OrdCost, TD_OrdPaid, TD_OrdPackage, TD_OrdStatus)" +
        " VALUES (@UserId, @Date, @Cost, @Paid, @Package, @Status);SELECT SCOPE_IDENTITY()";

    using (SqlConnection myConnection = new SqlConnection(connectionString))
    {
        myConnection.Open();
        SqlCommand myCommand = new SqlCommand(insertSql, myConnection);
        myCommand.Parameters.Add("@UserId", SqlDbType.VarChar).Value = userId;
        myCommand.Parameters.Add("@Date", SqlDbType.Date).Value = todaysDate;
        myCommand.Parameters.Add("@Cost", SqlDbType.Decimal).Value = docprice;
        myCommand.Parameters.Add("@Paid", SqlDbType.Decimal).Value = docpaid;
        myCommand.Parameters.Add("@Package", SqlDbType.Int).Value = packageId;
        myCommand.Parameters.Add("@Status", SqlDbType.Int).Value = orderstatus;
        myCommand.ExecuteNonQuery();  <---- FIRST RECORD WRITTEN

        // time to collect the last order id
        orderId = Convert.ToInt32(myCommand.ExecuteScalar());   <---- SECOND RECORD WRITTEN

        myConnection.Close();
    }
    return orderId;
}

1 ответ

Решение

Ваш код должен работать, если вы удалите строку myCommand.ExecuteNonQuery();

И то и другое ExecuteNonQuery() а также ExecuteScalar() отправьте команду на сервер SQL, единственное отличие состоит в том, как они обрабатывают результат. По сути, вы выполняете два INSERT заявления, которые вам не нужны.

Напомним, что в наше время очень редко можно использовать хардкорное кодирование ADO.NET. Обычно вы экономите много времени, если используете какой-либо ORM, например Entity Framework или мой личный фаворит, Dapper.NET.

Вот как вы можете переписать всю свою функцию, используя Dapper:

public static int CreateDocumentNumber(string userId, string todaysDate, decimal docprice, decimal docpaid, int packageId, int orderstatus)
{
    //create order 
    string connectionString = ConfigurationManager.ConnectionStrings["conString"].ConnectionString;
    string insertSql = "INSERT INTO [dbo].[LD_Orders](TD_OrdUserID, TD_OrdDate, TD_OrdCost, TD_OrdPaid, TD_OrdPackage, TD_OrdStatus)" +
        " VALUES (@UserId, @Date, @Cost, @Paid, @Package, @Status);SELECT SCOPE_IDENTITY()";

    using (SqlConnection myConnection = new SqlConnection(connectionString))
    {
        myConnection.Open();
        int orderId = myConnection.Query<int>(
            insertSql,
            new {
                   UserId = userId,
                   Date = todaysDate,
                   Cost = docprice,
                   Paid = docpaid,
                   Package = packageId,
                   Status = orderstatus
                }).Single();
    }
    return orderId;
}
Другие вопросы по тегам