Вопрос или проблема
Я хочу уменьшить количество моего продукта в базе данных через панель уменьшения продукта. Но если введённое число больше количества моего продукта, то есть если количество уменьшается и становится отрицательным, я хочу, чтобы выдала ошибку. Я не смог найти механизм этого решения и необходимые команды, можете помочь мне?
Я имею в виду, что хочу уменьшить число (которое является количеством продукта), но не хочу, чтобы число (количество продукта) стало отрицательным. Если вводимое значение больше количества, я хочу выдать ошибку, например, “У нас недостаточно продукта!”
Вот как я это пробую
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);
}
}
Объяснение кода:
-
Параметризованный запрос: Мы используем параметризованный запрос, чтобы избежать SQL-инъекций и улучшить безопасность. Вместо конкатенации строк вы передаете параметры в SQL-запрос.
-
Условие в WHERE: Условие
WHERE barkod = @barcode AND adet >= @amount
гарантирует, что обновление произойдет только в том случае, если количество товара (adet
) больше или равно введенному значению. Это предотвращает возникновение негативных значений. -
Проверка результата: Метод
ExecuteNonQuery()
возвращает количество затронутых строк. Если возвращаемое значение равно 0, это указывает на то, что обновление не произошло. В этом случае вы можете уведомить пользователя о том, что недостаточно товара или товар не найден.
Таким образом, данный подход обеспечит надежность вашей операции с количеством товара в базе данных, а также предотвратит ошибки, связанные с отрицательными значениями.