Декремент значения в SQL, но без отрицательных значений на C#

Вопрос или проблема

Я хочу уменьшить количество моего продукта в базе данных через панель уменьшения продукта. Но если введённое число больше количества моего продукта, то есть если количество уменьшается и становится отрицательным, я хочу, чтобы выдала ошибку. Я не смог найти механизм этого решения и необходимые команды, можете помочь мне?

Я имею в виду, что хочу уменьшить число (которое является количеством продукта), но не хочу, чтобы число (количество продукта) стало отрицательным. Если вводимое значение больше количества, я хочу выдать ошибку, например, “У нас недостаточно продукта!”

Вот как я это пробую

string constr = ConfigurationManager.ConnectionStrings["stok"].ConnectionString;
SqlConnection con = new SqlConnection(constr);
SqlCommand cmda;
SqlCommand cmdb;
con.Open();

SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM urunler WHERE barkod = '" + barkod.Text + "'", con);
SqlDataAdapter db = new SqlDataAdapter("SELECT * FROM urunler WHERE adet >= '0' AND barkod = '" + barkod.Text + "'", con);
DataSet ds = new DataSet();
DataSet dl = new DataSet();
da.Fill(ds);
db.Fill(dl);

if (ds.Tables[0].Rows.Count > 0)
{
    cmda = new SqlCommand("UPDATE urunler SET cikarTarih="" + cikarTarih.Text + ""WHERE barkod='" + barkod.Text + "'", con);
    cmdb = new SqlCommand("UPDATE urunler SET adet=adet-1 WHERE barkod='" + barkod.Text + "'", con);

    for (int i = Convert.ToInt32(adet.Text); i > 0 ; i--)
    {
        cmdb.ExecuteNonQuery();
        if (dl.Tables[0].Rows.Count < 0)
        {
            ClientScript.RegisterClientScriptBlock(this.GetType(), "K", "swal('Ошибка', 'Недостаточно количества продукта!', 'error')", true);
        }
    }
    cmda.ExecuteNonQuery();
    ClientScript.RegisterClientScriptBlock(this.GetType(), "K", "swal('Операция завершена', 'Количество продукта успешно обновлено!', 'success')", true);
}
else
{
    ClientScript.RegisterClientScriptBlock(this.GetType(), "K", "swal('Ошибка', 'Искомый продукт не найден!', 'error')", true);
}

con.Close();

Вот моё решение!

string constr = ConfigurationManager.ConnectionStrings["stok"].ConnectionString;
SqlConnection con = new SqlConnection(constr);
SqlCommand cmda;
SqlCommand cmdb;
con.Open();

SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM urunler WHERE barkod = '" + barkod.Text + "'", con);
SqlDataAdapter db = new SqlDataAdapter("SELECT * FROM urunler WHERE adet >='" + Convert.ToInt32(adet.Text) + "'AND barkod = '" + barkod.Text + "'", con);
DataSet ds = new DataSet();
DataSet dl = new DataSet();
da.Fill(ds);
db.Fill(dl);

if (ds.Tables[0].Rows.Count > 0)
{
    if (dl.Tables[0].Rows.Count > 0)
    {
        cmda = new SqlCommand("UPDATE urunler SET cikarTarih="" + cikarTarih.Text + ""WHERE barkod='" + barkod.Text + "'", con);
        cmdb = new SqlCommand("UPDATE urunler SET adet=adet-1 WHERE barkod='" + barkod.Text + "'", con);

        for (int i = Convert.ToInt32(adet.Text); i > 0 ; i--)
        {
            cmdb.ExecuteNonQuery();
        }
        cmda.ExecuteNonQuery();
        ClientScript.RegisterClientScriptBlock(this.GetType(), "K", "swal('Операция завершена', 'Количество продукта успешно обновлено!', 'success')", true);
    }
    else
    {
        ClientScript.RegisterClientScriptBlock(this.GetType(), "K", "swal('Ошибка', 'Недостаточно продукта!', 'error')", true);
    } 
}
else
{
    ClientScript.RegisterClientScriptBlock(this.GetType(), "K", "swal('Ошибка', 'Искомый продукт не найден!', 'error')", true);
}

con.Close();

Весь этот код можно заменить одной SqlCommand :

var sql=@"UPDATE urunler  
SET cikarTarih=@text, adet=adet-1 
WHERE barkod=@barcode AND adet>0";

using(var con = new SqlConnection(constr))
using (var cmd=new SqlCommand(con,sql))
{
    cmd.Parameters.Add("@barcode",SqlDbType.NVarchar,20).Value=barkod.Text ;
    cmd.Parameters.Add("@text",SqlDbType.NVarchar,20).Value=cikarTarih.Text ;

    var modified=cmd.ExecuteNonQuery();
    if(modified=0)
    {
        //Обновление не удалось, уведомите пользователя.
    }
}

Условие WHERE barkod=@barcode AND adet>0 будет уменьшать значение только если оно больше 0. UPDATE является атомарной операцией, поэтому нельзя выполнить два UPDATE одновременно и получить отрицательное значение.

В коде вопроса нет гарантии, что не будет отрицательных значений, поскольку другое соединение легко может считать то же начальное значение и уменьшить его. Чтобы избежать этого, будет нужна явная транзакция. Один UPDATE, впрочем, не требует дополнительной транзакции.

ExecuteNonQuery возвращает количество затронутых строк.

Код вопроса также страдает от серьезных проблем с SQL-инъекциями. Если кто-то введет '; DROP TABLE urunler ;-- в cikarTarih.Text, таблица будет удалена. Это очень легко избежать, используя параметризованные запросы с жестко типизированными параметрами.

Ответ или решение

Конечно! Давайте рассмотрим вашу проблему с уменьшением количества товара в базе данных с использованием C#. Для того чтобы избежать неприятных ситуаций, когда количество товара может стать отрицательным, вы можете использовать SQL-запрос с условием.

Как было упомянуто в вашем вопросе, было бы разумным рассмотреть вариант использования одномоментного обновления через SQL-запрос, который одновременно проверяет наличие достаточного количества товара и обновляет его.

Вот пример того, как это можно сделать:

string constr = ConfigurationManager.ConnectionStrings["stok"].ConnectionString;
var sql = @"UPDATE urunler  
SET cikarTarih = @text, adet = adet - @amount 
WHERE barkod = @barcode AND adet >= @amount";

using (var con = new SqlConnection(constr))
using (var cmd = new SqlCommand(sql, con))
{
    cmd.Parameters.Add("@barcode", SqlDbType.NVarChar, 20).Value = barkod.Text;
    cmd.Parameters.Add("@text", SqlDbType.NVarChar, 20).Value = cikarTarih.Text;
    cmd.Parameters.Add("@amount", SqlDbType.Int).Value = Convert.ToInt32(adet.Text);

    con.Open();
    var modified = cmd.ExecuteNonQuery();
    if (modified == 0)
    {
        // Здесь обновление не произошло, значит либо товар не был найден, либо недостаточно количества
        ClientScript.RegisterClientScriptBlock(this.GetType(), "K", "swal('Ошибка', 'Недостаточно товара на складе или товар не найден!', 'error')", true);
    }
    else
    {
        // Обновление прошло успешно
        ClientScript.RegisterClientScriptBlock(this.GetType(), "K", "swal('Успех', 'Количество товара было успешно обновлено!', 'success')", true);
    }
}

Объяснение кода:

  1. Параметризованный запрос: Мы используем параметризованный запрос, чтобы избежать SQL-инъекций и улучшить безопасность. Вместо конкатенации строк вы передаете параметры в SQL-запрос.

  2. Условие в WHERE: Условие WHERE barkod = @barcode AND adet >= @amount гарантирует, что обновление произойдет только в том случае, если количество товара (adet) больше или равно введенному значению. Это предотвращает возникновение негативных значений.

  3. Проверка результата: Метод ExecuteNonQuery() возвращает количество затронутых строк. Если возвращаемое значение равно 0, это указывает на то, что обновление не произошло. В этом случае вы можете уведомить пользователя о том, что недостаточно товара или товар не найден.

Таким образом, данный подход обеспечит надежность вашей операции с количеством товара в базе данных, а также предотвратит ошибки, связанные с отрицательными значениями.

Оцените материал
Добавить комментарий

Капча загружается...