Брисање података из базе¶
Стигао си до последње од четири основне CRUD операције: брисање података, тј. операције Delete. Као и код ажурирања, операција брисања захтева прецизно дефинисање одређеног реда у табели помоћу његовог јединственог идентификатора (примарног кључа). Поступак је веома опасан ако се не изведе пажљиво, јер једном обрисани подаци се, у већини случајева, не могу вратити.
Треба да имаш у виду да у комплексним базама података, често нећеш моћи да обришеш ред ако други редови у другим табелама зависе од њега (нпр. не можеш обрисати превозника ако постоје поруџбине које су повезане са њим). Ово се зове референцијални интегритет и штити базу од неконзистентних података. У том случају, DELETE наредба би изазвала грешку, коју би апликација требало да ухвати и обради. За потребе ове лекције, претпостави да таква ограничења не постоје.
У овој лекцији, направићеш апликацију која, слично претходној, учитава превознике у ComboBox и омогућава кориснику да изабере једног и обрише га из базе података, уз обавезну потврду пре саме операције.
Безбедност је и овде на првом месту. Креираћеш ускладиштену процедуру
usp_Obrisi која ће прихватити само један параметар: @ShipperID, тј. ID реда
који треба да буде обрисан. DELETE наредба ће користити WHERE клаузулу како би
осигурала да се обрише само и тачно тај ред.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE usp_Obrisi
@ShipperID INT
AS
BEGIN
DELETE FROM Shippers
WHERE ShipperID = @ShipperID;
END
GO
Као и код UPDATE процедуре, и овде je намерно изостављен SET NOCOUNT ON како
би C# апликација могла да добије тачан број обрисаних редова.
У класи Prevoznik можеш сада да напишеш и последњу CRUD методу: Obrisi().
Ова метода ће бити веома слична методи Azuriraj(). Прихватиће shipperId као
параметар, позваће ExecuteNonQuery() и вратиће bool вредност која означава
да ли је брисање било успешно.
public static bool Obrisi(int shipperId)
{
using (SqlConnection con = new SqlConnection(Konekcija.ConnString))
using (SqlCommand cmd = con.CreateCommand())
{
cmd.CommandText = "usp_Obrisi";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@ShipperID", shipperId);
con.Open();
int rowsAffected = cmd.ExecuteNonQuery();
return rowsAffected > 0;
}
}
Логика је идентична као код ажурирања: позива се процедура и проверава да ли је број погођених редова већи од нуле.
Презентациони слој за брисање је једноставан, али мора да укључи један веома важан елемент корисничког искуства: дијалог за потврду. Никада не би требало дозволити брисање података једним кликом. Увек треба питати корисника да ли је сигуран.
private void Form1_Load(object sender, EventArgs e)
{
UcitajPrevoznike();
}
private void UcitajPrevoznike()
{
try
{
List<Prevoznik> prevoznici = Prevoznik.UcitajSve();
cmbPrevoznici.DisplayMember = "CompanyName";
cmbPrevoznici.ValueMember = "ShipperID";
cmbPrevoznici.DataSource = prevoznici;
cmbPrevoznici.SelectedIndex = -1;
txtNazivKompanije.Clear();
txtTelefon.Clear();
}
catch (Exception ex)
{
MessageBox.Show("Greška prilikom učitavanja: " + ex.Message);
}
}
private void cmbPrevoznici_SelectedIndexChanged(object sender, EventArgs e)
{
if (cmbPrevoznici.SelectedItem is Prevoznik izabraniPrevoznik)
{
txtNazivKompanije.Text = izabraniPrevoznik.CompanyName;
txtTelefon.Text = izabraniPrevoznik.Phone;
}
else
{
txtNazivKompanije.Clear();
txtTelefon.Clear();
}
}
private void btnObrisi_Click(object sender, EventArgs e)
{
if (cmbPrevoznici.SelectedItem == null)
{
MessageBox.Show("Prevoznik mora biti izabran!");
return;
}
string poruka = $"Da li ste sigurni da želite da obrišete prevoznika: '{cmbPrevoznici.Text}'?";
DialogResult rezultat = MessageBox.Show(poruka, "Potvrda brisanja", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (rezultat != DialogResult.Yes)
{
return;
}
try
{
int idZaBrisanje = (int)cmbPrevoznici.SelectedValue;
bool uspeh = Prevoznik.Obrisi(idZaBrisanje);
if (uspeh)
{
MessageBox.Show("Prevoznik je uspešno obrisan");
UcitajPrevoznike();
}
else
{
MessageBox.Show("Desila se greška. Brisanje nije uspelo!");
}
}
catch (Exception ex)
{
if (ex.Message.Contains("REFERENCE constraint"))
{
MessageBox.Show("Brisanje nije moguće zbog referencijalnog integriteta!");
}
else
{
MessageBox.Show("Desila se greška: " + ex.Message);
}
}
}