📅 19 Nisan 2026, Pazar
📚 Ders Kitapları ✉ İletişim
@ydiner.gen.tr İlköğretim & Lise Düzeyi Kaynak Site "Bilgi paylaştıkça çoğalır"
🏠 Ana Sayfa
  • 🧊 3D Tasarım
  • Animasyon
  • ⚡ Arduino
  • 📌 Genel
  • 🎨 Grafik
  • Pardus
  • 💻 Programlama
  • Robotik ve Kodlama
  • 🗄️ SQL
  • 🌐 Web Tasarım
  • 🤖 Yapay Zeka
  • Programlama

    stok uygulaması 20 Nisan

    18 Nisan 2026 aydiner

    SQL Server’da StokDB veritabanını ve tablolarını oluşturmak.

    Kategoriler          Urunler
    -----------          -------
    KategoriID (PK)  ←── KategoriID (FK)
    KategoriAdi          UrunID (PK)
                         UrunAdi
                         Barkod
                         Fiyat
                         StokMiktari
                         EklenmeTarihi
    

    SQL Script — SSMS veya Azure Data Studio’da çalıştırın

    -- 1. Veritabanı oluştur
    CREATE DATABASE StokDB;
    GO
    
    USE StokDB;
    GO
    
    -- 2. Kategoriler tablosu
    CREATE TABLE Kategoriler (
        KategoriID   INT IDENTITY(1,1) PRIMARY KEY,
        KategoriAdi  NVARCHAR(100) NOT NULL
    );
    GO
    
    -- 3. Ürünler tablosu
    CREATE TABLE Urunler (
        UrunID        INT IDENTITY(1,1) PRIMARY KEY,
        UrunAdi       NVARCHAR(200) NOT NULL,
        Barkod        NVARCHAR(50)  UNIQUE,
        Fiyat         DECIMAL(10,2) NOT NULL DEFAULT 0,
        StokMiktari   INT           NOT NULL DEFAULT 0,
        KategoriID    INT           FOREIGN KEY REFERENCES Kategoriler(KategoriID),
        EklenmeTarihi DATETIME      DEFAULT GETDATE()
    );
    GO
    
    -- 4. Örnek kategoriler
    INSERT INTO Kategoriler (KategoriAdi) VALUES
    ('Elektronik'),
    ('Gıda'),
    ('Giyim'),
    ('Kırtasiye'),
    ('Kozmetik');
    GO
    
    -- 5. Örnek ürünler
    INSERT INTO Urunler (UrunAdi, Barkod, Fiyat, StokMiktari, KategoriID) VALUES
    ('Laptop',         '8680001', 15000.00, 10, 1),
    ('Şeker 1kg',      '8680002',    25.50, 50, 2),
    ('Beyaz Gömlek',   '8680003',   350.00, 30, 3),
    ('Tükenmez Kalem', '8680004',     5.00,100, 4),
    ('Şampuan',        '8680005',    45.00, 40, 5);
    GO
    
    -- 6. Kontrol sorgusu
    SELECT u.UrunID, u.UrunAdi, u.Barkod, u.Fiyat, u.StokMiktari,
           k.KategoriAdi, u.EklenmeTarihi
    FROM Urunler u
    JOIN Kategoriler k ON u.KategoriID = k.KategoriID;
    
    

    Visual Studio’da projeyi kurmak ve SQL Server bağlantısını test etmek.

    StokYonetimi/
    ├── Forms/
    │   ├── AnaSayfa.cs          ← Ana menü
    │   ├── UrunListeFormu.cs    ← Listeleme + Silme
    │   ├── UrunEkleFormu.cs     ← Ekleme
    │   └── UrunGuncelleFormu.cs ← Güncelleme
    ├── Helpers/
    │   └── DbHelper.cs          ← Veritabanı bağlantı sınıfı
    └── Program.cs
    
    

    PM> Install-Package Microsoft.Data.SqlClient

    Helpers klasörü oluşturun, içine DbHelper.cs ekleyin

    using Microsoft.Data.SqlClient;
    
    namespace StokYonetimi.Helpers
    {
        public static class DbHelper
        {
            // ⚠️ Kendi sunucu adınıza göre değiştirin
            private static readonly string ConnectionString =
                "Server=.\\SQLEXPRESS; Database=StokDB; Trusted_Connection=True; TrustServerCertificate=True;";
    
            public static SqlConnection GetConnection()
            {
                return new SqlConnection(ConnectionString);
            }
        }
    }
    
    

    Not: Sunucu adı için SSMS’te bağlandığınız adı kullanın.
    Örnek: Server=BILGISAYAR-ADI\\SQLEXPRESS

    AnaSayfa.cs formunun Load olayına ekleyin:

    using Microsoft.Data.SqlClient;
    using StokYonetimi.Helpers;
    
    private void AnaSayfa_Load(object sender, EventArgs e)
    {
        try
        {
            using (var conn = DbHelper.GetConnection())
            {
                conn.Open();
                MessageBox.Show("✅ Veritabanı bağlantısı BAŞARILI!", "Bağlantı Testi",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("❌ Bağlantı hatası: " + ex.Message, "Hata",
                MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
    
    

    Ana Sayfa Tasarımı (AnaSayfa.cs)

    Ana Sayfa Tasarımı (AnaSayfa.cs)
    Designer’da şu kontrolları ekleyin:

    Kontrol Name Text
    Label lblBaslik STOK YÖNETİM SİSTEMİ
    Button btnUrunler 📋 Ürün Listesi
    Button btnEkle ➕ Yeni Ürün Ekle
    Button btnCikis 🚪 Çıkış
    ✅ Saat 2 Kontrol Listesi
    WinForms projesi oluşturuldu
    Microsoft.Data.SqlClient paketi yüklendi
    DbHelper.cs oluşturuldu
    Bağlantı testi başarılı
    Ana sayfa tasarlandı
    ⏱️ 3. SAAT — Ürün Ekleme Formu
    📌 Hedef
    UrunEkleFormu.cs ile veritabanına yeni ürün eklemek.

    🎨 Form Tasarımı
    Kontrol Name Text/Özellik
    Label — Ürün Adı:
    TextBox txtUrunAdi —
    Label — Barkod:
    TextBox txtBarkod —
    Label — Fiyat:
    TextBox txtFiyat —
    Label — Stok Miktarı:
    TextBox txtStokMiktari —
    Label — Kategori:
    ComboBox cmbKategori DropDownStyle: DropDownList
    Button btnKaydet 💾 Kaydet
    Button btnTemizle 🗑️ Temizle
    Button btnIptal ✖️ İptal
    💻 UrunEkleFormu.cs — Tam Kod
    csharp
    using System;
    using System.Windows.Forms;
    using Microsoft.Data.SqlClient;
    using StokYonetimi.Helpers;
    namespace StokYonetimi.Forms
    {
    public partial class UrunEkleFormu : Form
    {
    public UrunEkleFormu()
    {
    InitializeComponent();
    }
    // Form açılırken kategorileri yükle
    private void UrunEkleFormu_Load(object sender, EventArgs e)
    {
    KategorileriYukle();
    }
    private void KategorileriYukle()
    {
    try
    {
    using (var conn = DbHelper.GetConnection())
    {
    conn.Open();
    string sql = “SELECT KategoriID, KategoriAdi FROM Kategoriler ORDER BY KategoriAdi”;
    using (var cmd = new SqlCommand(sql, conn))
    using (var reader = cmd.ExecuteReader())
    {
    cmbKategori.Items.Clear();
    while (reader.Read())
    {
    cmbKategori.Items.Add(new
    {
    ID = reader.GetInt32(0),
    Ad = reader.GetString(1)
    });
    }
    }
    }
    cmbKategori.DisplayMember = “Ad”;
    cmbKategori.ValueMember = “ID”;
    }
    catch (Exception ex)
    {
    MessageBox.Show(“Kategori yükleme hatası: ” + ex.Message, “Hata”,
    MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    }
    // Kaydet butonu
    private void btnKaydet_Click(object sender, EventArgs e)
    {
    // —– Validasyon —–
    if (string.IsNullOrWhiteSpace(txtUrunAdi.Text))
    {
    MessageBox.Show(“Ürün adı boş olamaz!”, “Uyarı”,
    MessageBoxButtons.OK, MessageBoxIcon.Warning);
    txtUrunAdi.Focus();
    return;
    }
    if (!decimal.TryParse(txtFiyat.Text, out decimal fiyat) || fiyat < 0)
    {
    MessageBox.Show(“Geçerli bir fiyat girin!”, “Uyarı”,
    MessageBoxButtons.OK, MessageBoxIcon.Warning);
    txtFiyat.Focus();
    return;
    }
    if (!int.TryParse(txtStokMiktari.Text, out int stok) || stok < 0)
    {
    MessageBox.Show(“Geçerli bir stok miktarı girin!”, “Uyarı”,
    MessageBoxButtons.OK, MessageBoxIcon.Warning);
    txtStokMiktari.Focus();
    return;
    }
    if (cmbKategori.SelectedItem == null)
    {
    MessageBox.Show(“Lütfen bir kategori seçin!”, “Uyarı”,
    MessageBoxButtons.OK, MessageBoxIcon.Warning);
    return;
    }
    // —– Veritabanına Kaydet —–
    try
    {
    // Seçilen kategorinin ID’sini al
    dynamic seciliKategori = cmbKategori.SelectedItem;
    int kategoriId = seciliKategori.ID;
    using (var conn = DbHelper.GetConnection())
    {
    conn.Open();
    string sql = @”INSERT INTO Urunler
    (UrunAdi, Barkod, Fiyat, StokMiktari, KategoriID)
    VALUES
    (@UrunAdi, @Barkod, @Fiyat, @StokMiktari, @KategoriID)”;
    using (var cmd = new SqlCommand(sql, conn))
    {
    cmd.Parameters.AddWithValue(“@UrunAdi”, txtUrunAdi.Text.Trim());
    cmd.Parameters.AddWithValue(“@Barkod”, string.IsNullOrWhiteSpace(txtBarkod.Text)
    ? DBNull.Value
    : (object)txtBarkod.Text.Trim());
    cmd.Parameters.AddWithValue(“@Fiyat”, fiyat);
    cmd.Parameters.AddWithValue(“@StokMiktari”, stok);
    cmd.Parameters.AddWithValue(“@KategoriID”, kategoriId);
    cmd.ExecuteNonQuery();
    }
    }
    MessageBox.Show(“✅ Ürün başarıyla eklendi!”, “Başarılı”,
    MessageBoxButtons.OK, MessageBoxIcon.Information);
    FormTemizle();
    }
    catch (SqlException ex) when (ex.Number == 2627) // Unique constraint (Barkod)
    {
    MessageBox.Show(“Bu barkod zaten kayıtlı! Farklı bir barkod girin.”, “Hata”,
    MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    catch (Exception ex)
    {
    MessageBox.Show(“Kayıt hatası: ” + ex.Message, “Hata”,
    MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    }
    // Temizle butonu
    private void btnTemizle_Click(object sender, EventArgs e)
    {
    FormTemizle();
    }
    private void FormTemizle()
    {
    txtUrunAdi.Clear();
    txtBarkod.Clear();
    txtFiyat.Clear();
    txtStokMiktari.Clear();
    cmbKategori.SelectedIndex = -1;
    txtUrunAdi.Focus();
    }
    // İptal butonu
    private void btnIptal_Click(object sender, EventArgs e)
    {
    this.Close();
    }
    }
    }
    ✅ Saat 3 Kontrol Listesi
    UrunEkleFormu tasarlandı
    Kategoriler ComboBox’a yükleniyor
    Validasyonlar çalışıyor
    Ürün veritabanına kaydediliyor
    Barkod çakışması hatası yakalanıyor
    ⏱️ 4. SAAT — Ürünleri Listeleme & Silme
    📌 Hedef
    UrunListeFormu.cs ile tüm ürünleri listelemek ve seçilen ürünü silmek.

    🎨 Form Tasarımı
    Kontrol Name Özellik
    TextBox txtArama PlaceholderText: “🔍 Ürün adı veya barkod ara…”
    Button btnAra 🔍 Ara
    Button btnTumunuGoster 📋 Tümünü Göster
    DataGridView dgvUrunler FullRowSelect, ReadOnly
    Button btnSil 🗑️ Seçileni Sil
    Button btnDuzenle ✏️ Düzenle
    Label lblToplamKayit —
    💻 UrunListeFormu.cs — Tam Kod
    csharp
    using System;
    using System.Data;
    using System.Windows.Forms;
    using Microsoft.Data.SqlClient;
    using StokYonetimi.Helpers;
    namespace StokYonetimi.Forms
    {
    public partial class UrunListeFormu : Form
    {
    public UrunListeFormu()
    {
    InitializeComponent();
    }
    private void UrunListeFormu_Load(object sender, EventArgs e)
    {
    DataGridViewAyarla();
    UrunleriYukle();
    }
    // DataGridView görsel ayarları
    private void DataGridViewAyarla()
    {
    dgvUrunler.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
    dgvUrunler.MultiSelect = false;
    dgvUrunler.ReadOnly = true;
    dgvUrunler.AllowUserToAddRows = false;
    dgvUrunler.AllowUserToDeleteRows = false;
    dgvUrunler.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
    }
    // Tüm ürünleri yükle
    private void UrunleriYukle(string aramaMetni = “”)
    {
    try
    {
    using (var conn = DbHelper.GetConnection())
    {
    conn.Open();
    string sql = @”
    SELECT
    u.UrunID AS [ID],
    u.UrunAdi AS [Ürün Adı],
    u.Barkod AS [Barkod],
    k.KategoriAdi AS [Kategori],
    u.Fiyat AS [Fiyat (₺)],
    u.StokMiktari AS [Stok],
    u.EklenmeTarihi AS [Eklenme Tarihi]
    FROM Urunler u
    JOIN Kategoriler k ON u.KategoriID = k.KategoriID
    WHERE u.UrunAdi LIKE @Arama OR u.Barkod LIKE @Arama
    ORDER BY u.UrunAdi”;
    using (var cmd = new SqlCommand(sql, conn))
    {
    cmd.Parameters.AddWithValue(“@Arama”, “%” + aramaMetni + “%”);
    var adapter = new SqlDataAdapter(cmd);
    var tablo = new DataTable();
    adapter.Fill(tablo);
    dgvUrunler.DataSource = tablo;
    lblToplamKayit.Text = $”Toplam: {tablo.Rows.Count} kayıt”;
    }
    }
    }
    catch (Exception ex)
    {
    MessageBox.Show(“Veri yükleme hatası: ” + ex.Message, “Hata”,
    MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    }
    // Ara butonu
    private void btnAra_Click(object sender, EventArgs e)
    {
    UrunleriYukle(txtArama.Text.Trim());
    }
    // Tümünü Göster butonu
    private void btnTumunuGoster_Click(object sender, EventArgs e)
    {
    txtArama.Clear();
    UrunleriYukle();
    }
    // Enter tuşuyla arama
    private void txtArama_KeyDown(object sender, KeyEventArgs e)
    {
    if (e.KeyCode == Keys.Enter)
    UrunleriYukle(txtArama.Text.Trim());
    }
    // Sil butonu
    private void btnSil_Click(object sender, EventArgs e)
    {
    if (dgvUrunler.SelectedRows.Count == 0)
    {
    MessageBox.Show(“Lütfen silmek istediğiniz ürünü seçin!”, “Uyarı”,
    MessageBoxButtons.OK, MessageBoxIcon.Warning);
    return;
    }
    // Seçilen satırdan ID ve adı al
    var seciliSatir = dgvUrunler.SelectedRows[0];
    int urunId = Convert.ToInt32(seciliSatir.Cells[“ID”].Value);
    string urunAdi = seciliSatir.Cells[“Ürün Adı”].Value.ToString();
    // Onay sor
    var sonuc = MessageBox.Show(
    $”‘{urunAdi}’ ürününü silmek istediğinizden emin misiniz?”,
    “Silme Onayı”,
    MessageBoxButtons.YesNo,
    MessageBoxIcon.Question);
    if (sonuc != DialogResult.Yes) return;
    // Veritabanından sil
    try
    {
    using (var conn = DbHelper.GetConnection())
    {
    conn.Open();
    string sql = “DELETE FROM Urunler WHERE UrunID = @UrunID”;
    using (var cmd = new SqlCommand(sql, conn))
    {
    cmd.Parameters.AddWithValue(“@UrunID”, urunId);
    cmd.ExecuteNonQuery();
    }
    }
    MessageBox.Show(“✅ Ürün başarıyla silindi!”, “Başarılı”,
    MessageBoxButtons.OK, MessageBoxIcon.Information);
    UrunleriYukle(); // Listeyi yenile
    }
    catch (Exception ex)
    {
    MessageBox.Show(“Silme hatası: ” + ex.Message, “Hata”,
    MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    }
    // Düzenle butonu
    private void btnDuzenle_Click(object sender, EventArgs e)
    {
    if (dgvUrunler.SelectedRows.Count == 0)
    {
    MessageBox.Show(“Lütfen düzenlemek istediğiniz ürünü seçin!”, “Uyarı”,
    MessageBoxButtons.OK, MessageBoxIcon.Warning);
    return;
    }
    int urunId = Convert.ToInt32(dgvUrunler.SelectedRows[0].Cells[“ID”].Value);
    var guncelleFormu = new UrunGuncelleFormu(urunId);
    guncelleFormu.ShowDialog();
    UrunleriYukle(); // Güncelleme sonrası listeyi yenile
    }
    }
    }
    ✅ Saat 4 Kontrol Listesi
    DataGridView ürünleri listeliyor
    Arama kutusu çalışıyor
    Enter tuşuyla arama yapılıyor
    Silme onay penceresi çıkıyor
    Silme sonrası liste yenileniyor
    ⏱️ 5. SAAT — Ürün Güncelleme
    📌 Hedef
    Seçilen ürünün bilgilerini düzenleyip veritabanını güncellemek.

    🎨 Form Tasarımı
    UrunEkleFormu ile aynı kontroller — sadece başlık ve buton metni farklı.

    Kontrol Name Açıklama
    TextBox txtUrunAdi —
    TextBox txtBarkod —
    TextBox txtFiyat —
    TextBox txtStokMiktari —
    ComboBox cmbKategori —
    Button btnGuncelle 💾 Güncelle
    Button btnIptal ✖️ İptal
    💻 UrunGuncelleFormu.cs — Tam Kod
    csharp
    using System;
    using System.Windows.Forms;
    using Microsoft.Data.SqlClient;
    using StokYonetimi.Helpers;
    namespace StokYonetimi.Forms
    {
    public partial class UrunGuncelleFormu : Form
    {
    private readonly int _urunId;
    // Constructor: güncellenecek ürünün ID’si parametre olarak gelir
    public UrunGuncelleFormu(int urunId)
    {
    InitializeComponent();
    _urunId = urunId;
    }
    private void UrunGuncelleFormu_Load(object sender, EventArgs e)
    {
    KategorileriYukle();
    UrunBilgileriniGetir();
    }
    private void KategorileriYukle()
    {
    try
    {
    using (var conn = DbHelper.GetConnection())
    {
    conn.Open();
    string sql = “SELECT KategoriID, KategoriAdi FROM Kategoriler ORDER BY KategoriAdi”;
    using (var cmd = new SqlCommand(sql, conn))
    using (var reader = cmd.ExecuteReader())
    {
    cmbKategori.Items.Clear();
    while (reader.Read())
    {
    cmbKategori.Items.Add(new
    {
    ID = reader.GetInt32(0),
    Ad = reader.GetString(1)
    });
    }
    }
    }
    cmbKategori.DisplayMember = “Ad”;
    cmbKategori.ValueMember = “ID”;
    }
    catch (Exception ex)
    {
    MessageBox.Show(“Kategori yükleme hatası: ” + ex.Message);
    }
    }
    // Mevcut ürün bilgilerini forma getir
    private void UrunBilgileriniGetir()
    {
    try
    {
    using (var conn = DbHelper.GetConnection())
    {
    conn.Open();
    string sql = @”SELECT UrunAdi, Barkod, Fiyat, StokMiktari, KategoriID
    FROM Urunler WHERE UrunID = @UrunID”;
    using (var cmd = new SqlCommand(sql, conn))
    {
    cmd.Parameters.AddWithValue(“@UrunID”, _urunId);
    using (var reader = cmd.ExecuteReader())
    {
    if (reader.Read())
    {
    txtUrunAdi.Text = reader[“UrunAdi”].ToString();
    txtBarkod.Text = reader[“Barkod”] == DBNull.Value
    ? “” : reader[“Barkod”].ToString();
    txtFiyat.Text = reader[“Fiyat”].ToString();
    txtStokMiktari.Text = reader[“StokMiktari”].ToString();
    // Kategoriye ait ComboBox öğesini seç
    int kategoriId = Convert.ToInt32(reader[“KategoriID”]);
    for (int i = 0; i < cmbKategori.Items.Count; i++)
    {
    dynamic item = cmbKategori.Items[i];
    if (item.ID == kategoriId)
    {
    cmbKategori.SelectedIndex = i;
    break;
    }
    }
    }
    }
    }
    }
    }
    catch (Exception ex)
    {
    MessageBox.Show(“Veri getirme hatası: ” + ex.Message, “Hata”,
    MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    }
    // Güncelle butonu
    private void btnGuncelle_Click(object sender, EventArgs e)
    {
    // —– Validasyon —–
    if (string.IsNullOrWhiteSpace(txtUrunAdi.Text))
    {
    MessageBox.Show(“Ürün adı boş olamaz!”, “Uyarı”,
    MessageBoxButtons.OK, MessageBoxIcon.Warning);
    return;
    }
    if (!decimal.TryParse(txtFiyat.Text, out decimal fiyat) || fiyat < 0)
    {
    MessageBox.Show(“Geçerli bir fiyat girin!”, “Uyarı”,
    MessageBoxButtons.OK, MessageBoxIcon.Warning);
    return;
    }
    if (!int.TryParse(txtStokMiktari.Text, out int stok) || stok < 0)
    {
    MessageBox.Show(“Geçerli bir stok miktarı girin!”, “Uyarı”,
    MessageBoxButtons.OK, MessageBoxIcon.Warning);
    return;
    }
    if (cmbKategori.SelectedItem == null)
    {
    MessageBox.Show(“Lütfen bir kategori seçin!”, “Uyarı”,
    MessageBoxButtons.OK, MessageBoxIcon.Warning);
    return;
    }
    // —– Veritabanını Güncelle —–
    try
    {
    dynamic seciliKategori = cmbKategori.SelectedItem;
    int kategoriId = seciliKategori.ID;
    using (var conn = DbHelper.GetConnection())
    {
    conn.Open();
    string sql = @”UPDATE Urunler SET
    UrunAdi = @UrunAdi,
    Barkod = @Barkod,
    Fiyat = @Fiyat,
    StokMiktari = @StokMiktari,
    KategoriID = @KategoriID
    WHERE UrunID = @UrunID”;
    using (var cmd = new SqlCommand(sql, conn))
    {
    cmd.Parameters.AddWithValue(“@UrunAdi”, txtUrunAdi.Text.Trim());
    cmd.Parameters.AddWithValue(“@Barkod”, string.IsNullOrWhiteSpace(txtBarkod.Text)
    ? DBNull.Value
    : (object)txtBarkod.Text.Trim());
    cmd.Parameters.AddWithValue(“@Fiyat”, fiyat);
    cmd.Parameters.AddWithValue(“@StokMiktari”, stok);
    cmd.Parameters.AddWithValue(“@KategoriID”, kategoriId);
    cmd.Parameters.AddWithValue(“@UrunID”, _urunId);
    cmd.ExecuteNonQuery();
    }
    }
    MessageBox.Show(“✅ Ürün başarıyla güncellendi!”, “Başarılı”,
    MessageBoxButtons.OK, MessageBoxIcon.Information);
    this.Close();
    }
    catch (SqlException ex) when (ex.Number == 2627)
    {
    MessageBox.Show(“Bu barkod zaten kayıtlı!”, “Hata”,
    MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    catch (Exception ex)
    {
    MessageBox.Show(“Güncelleme hatası: ” + ex.Message, “Hata”,
    MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    }
    // İptal butonu
    private void btnIptal_Click(object sender, EventArgs e)
    {
    this.Close();
    }
    }
    }
    ✅ Saat 5 Kontrol Listesi
    Güncelleme formu açılıyor
    Mevcut ürün bilgileri forma geliyor
    Kategori doğru seçili geliyor
    Güncelleme veritabanına yansıyor
    Liste otomatik yenileniyor
    ⏱️ 6. SAAT — Son Dokunuşlar & Test
    📌 Hedef
    Stok durumuna göre renklendirme, kategori bazlı filtreleme, genel test.

    🎨 Özellik 1 — Stok Uyarısı (Kırmızı Renk)
    UrunListeFormu.cs’e ekleyin — DataGridView’in CellFormatting olayına:

    csharp
    private void dgvUrunler_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
    if (e.RowIndex < 0) return;
    var satir = dgvUrunler.Rows[e.RowIndex];
    var stokHucresi = satir.Cells[“Stok”];
    if (stokHucresi.Value != null && int.TryParse(stokHucresi.Value.ToString(), out int stok))
    {
    if (stok == 0)
    {
    // Stok yok → kırmızı
    satir.DefaultCellStyle.BackColor = Color.FromArgb(255, 200, 200);
    satir.DefaultCellStyle.ForeColor = Color.DarkRed;
    }
    else if (stok < 5)
    {
    // Stok az → sarı
    satir.DefaultCellStyle.BackColor = Color.FromArgb(255, 255, 180);
    satir.DefaultCellStyle.ForeColor = Color.DarkOliveGreen;
    }
    else
    {
    satir.DefaultCellStyle.BackColor = Color.White;
    satir.DefaultCellStyle.ForeColor = Color.Black;
    }
    }
    }
    📊 Özellik 2 — Stok Özet Raporu
    Ana sayfaya veya liste formuna ekleyebilirsiniz:

    csharp
    private void StokRaporuGoster()
    {
    try
    {
    using (var conn = DbHelper.GetConnection())
    {
    conn.Open();
    string sql = @”
    SELECT
    COUNT(*) AS ToplamUrun,
    SUM(StokMiktari) AS ToplamStok,
    COUNT(CASE WHEN StokMiktari = 0 THEN 1 END) AS TukenenUrun,
    COUNT(CASE WHEN StokMiktari < 5 AND StokMiktari > 0 THEN 1 END) AS KritikStok
    FROM Urunler”;
    using (var cmd = new SqlCommand(sql, conn))
    using (var reader = cmd.ExecuteReader())
    {
    if (reader.Read())
    {
    lblToplamUrun.Text = $”Toplam Ürün: {reader[“ToplamUrun”]}”;
    lblToplamStok.Text = $”Toplam Stok: {reader[“ToplamStok”]}”;
    lblTukenenUrun.Text = $”Tükenen: {reader[“TukenenUrun”]}”;
    lblKritikStok.Text = $”Kritik Stok: {reader[“KritikStok”]}”;
    }
    }
    }
    }
    catch (Exception ex)
    {
    MessageBox.Show(“Rapor hatası: ” + ex.Message);
    }
    }
    🧪 Final Test Senaryoları
    # Test Adımı Beklenen Sonuç
    1 Uygulama başlat DB bağlantısı başarılı
    2 Yeni ürün ekle (boş ad ile) “Ürün adı boş olamaz!” uyarısı
    3 Aynı barkodla 2. ürün ekle “Barkod zaten kayıtlı!” hatası
    4 Geçersiz fiyat gir (harf) “Geçerli bir fiyat girin!” uyarısı
    5 Ürün ekle (geçerli verilerle) “Başarıyla eklendi!” mesajı
    6 Listede ürünü arayla Sadece eşleşenler gelsin
    7 Ürünü düzenle & kaydet Listede değişsin
    8 Ürünü sil (Evet ile) Listeden kalksın
    9 Ürünü sil (Hayır ile) Silinmesin
    10 Stok=0 olan ürün Kırmızı renk gösterin
    ✅ Saat 6 Kontrol Listesi
    Stok renklendirme çalışıyor (kırmızı/sarı/beyaz)
    Stok raporu doğru sayıları gösteriyor
    Tüm test senaryoları geçti
    Uygulama hatasız çalışıyor
    📁 SQL Script — Hızlı Referans
    sql
    — Tüm ürünleri listele
    SELECT u.*, k.KategoriAdi FROM Urunler u JOIN Kategoriler k ON u.KategoriID = k.KategoriID;
    — Tükenen ürünler
    SELECT * FROM Urunler WHERE StokMiktari = 0;
    — Kritik stok (5’ten az)
    SELECT * FROM Urunler WHERE StokMiktari > 0 AND StokMiktari < 5;
    — Kategoriye göre ürün sayısı
    SELECT k.KategoriAdi, COUNT(u.UrunID) AS UrunSayisi
    FROM Kategoriler k LEFT JOIN Urunler u ON k.KategoriID = u.KategoriID
    GROUP BY k.KategoriAdi;
    — En pahalı 5 ürün
    SELECT TOP 5 UrunAdi, Fiyat FROM Urunler ORDER BY Fiyat DESC;
    🚨 Sık Yapılan Hatalar & Çözümleri
    Hata Sebep Çözüm
    Cannot open server Sunucu adı yanlış Connection string’de server adını kontrol et
    Login failed Windows auth çalışmıyor Trusted_Connection=True ekle
    SSL connection error Sertifika sorunu TrustServerCertificate=True ekle
    Object reference null ComboBox seçilmedi SelectedItem == null kontrolü ekle
    Input string not in correct format TryParse kullanılmadı decimal.TryParse ile kontrol et
    Duplicate key error Aynı barkod SqlException.Number == 2627 yakala