Mobil Menü

Veri Tabanlı Bağlı Liste Uygulaması: C# ile MySQL Entegrasyonu

Bu makalede, C# programlama dili ve MySQL veritabanı kullanarak geliştirilmiş veritabanı destekli bağlı liste uygulamasını inceleyeceğiz. Bu uygulama, temel veri yapılarından biri olan bağlı listelerin kalıcı depolama ile nasıl entegre edilebileceğini göstermektedir.

Proje Genel Bakış

Bağlı Liste Uygulaması, Windows Forms ile geliştirilmiş ve MySQL veritabanına entegre edilmiş bir veri yapısı örneğidir. Uygulamanın temel özellikleri:

  • Başa ve sona eleman ekleme fonksiyonları
  • Belirli pozisyona eleman ekleme özelliği
  • Eleman silme işlevselliği
  • Listeyi tamamen temizleme seçeneği
  • Verilerin kalıcı depolanması için MySQL entegrasyonu

Teknik Detaylar

Uygulama, çift yönlü bağlı liste mantığıyla çalışmaktadır. Her düğüm (node) veritabanında ayrı bir kayıt olarak saklanır ve NextId ve PreviousId alanlarıyla birbirine bağlanır.

MySQL Tablo Yapısı

CREATE TABLE LinkedListNodes (
    Id INT AUTO_INCREMENT PRIMARY KEY,
    Data VARCHAR(255),
    NextId INT NULL,
    PreviousId INT NULL
);

Temel Fonksiyonlar

  1. Başa Ekleme (AddFirst): Yeni düğümü listenin başına ekler ve mevcut ilk düğümün bağlantılarını günceller.
  2. Sona Ekleme (AddLast): Yeni düğümü listenin sonuna ekler ve mevcut son düğümün bağlantılarını günceller.
  3. Araya Ekleme (InsertAt): Belirtilen pozisyona yeni düğüm ekler, önceki ve sonraki düğümlerin bağlantılarını ayarlar.
  4. Silme (Remove): Seçilen düğümü listeden çıkarır ve komşu düğümleri birbirine bağlar.

Kullanım Senaryoları

Bu uygulama özellikle şu durumlarda faydalıdır:

  • Veri yapıları eğitimi için görsel bir araç olarak
  • Sıralı veri depolama ihtiyaçlarında
  • Kalıcı bağlı liste uygulamaları geliştirirken
  • Algoritma analizi yaparken

Performans Optimizasyonu

Uygulama, veritabanı işlemlerini optimize etmek için:

  • Transaction kullanımı (şu anki versiyonda tam olarak uygulanmamış olsa da eklenebilir)
  • Index’li sorgular (Id alanı otomatik olarak indexlenir)
  • Minimum veritabanı erişimi için optimize edilmiş sorgular

Geliştirilebilir Yönler

Projenin gelecek versiyonlarında şu özellikler eklenebilir:

  1. Transaction yönetimi için MySQL transaction desteği
  2. Çoklu dil desteği ile uluslararasılaştırma
  3. Daha karmaşık veri tipleri desteği
  4. JSON import/export özelliği
  5. Otomatik yedekleme mekanizması

Sonuç

Bu C# ve MySQL entegrasyonu, geleneksel veri yapılarının modern veritabanı sistemleriyle nasıl birleştirilebileceğinin güzel bir örneğidir. Öğrenciler ve yazılım geliştiriciler için hem eğitici hem de pratik bir proje olarak kullanılabilir.

Not: Bu program kodları eğitim ve öğretim amaçlı yapılmış olup hatalar ve sorunlar olabilmektedir. Lütfen kodu kullanırken dikkatli olunuz!

using System.Data;
using MySql.Data.MySqlClient;

namespace BağlıListe
{
    public partial class Form1 : Form
    {
      
          private MySqlConnection connection;
        private string server = "localhost";
        private string database = "LinkedListDB";
        private string uid = "root";
        private string password = "";

        public Form1()
        {
            InitializeComponent();
            InitializeDatabaseConnection();
            InitializeFormControls();
            LoadLinkedListFromDatabase();
        }

        private void InitializeDatabaseConnection()
        {
            string connectionString = $"SERVER={server};DATABASE={database};UID={uid};PASSWORD={password};";
            connection = new MySqlConnection(connectionString);

            try
            {
                connection.Open();
            }
            catch (MySqlException ex)
            {
                MessageBox.Show($"MySQL Bağlantı Hatası: {ex.Message}");
            }
        }

        private void InitializeFormControls()
        {
            // Form özellikleri
            this.Text = "Bağlı Liste Uygulaması";
            this.Size = new Size(620, 500);
            this.StartPosition = FormStartPosition.CenterScreen;

            // Kontroller
            Label lblData = new Label
            {
                Text = "Veri:",
                Location = new Point(20, 20),
                AutoSize = true
            };

            TextBox txtData = new TextBox
            {
                Name = "txtData",
                Location = new Point(100, 20),
                Size = new Size(150, 20)
            };

            Label lblPosition = new Label
            {
                Text = "Pozisyon:",
                Location = new Point(20, 50),
                AutoSize = true
            };

            TextBox txtPosition = new TextBox
            {
                Name = "txtPosition",
                Location = new Point(100, 50),
                Size = new Size(50, 20),
                Text = "0"
            };

            Button btnAddFirst = new Button
            {
                Text = "Başa Ekle",
                Location = new Point(20, 80),
                Size = new Size(100, 30)
            };
            btnAddFirst.Click += BtnAddFirst_Click;

            Button btnAddLast = new Button
            {
                Text = "Sona Ekle",
                Location = new Point(130, 80),
                Size = new Size(100, 30)
            };
            btnAddLast.Click += BtnAddLast_Click;

            Button btnInsertAt = new Button
            {
                Text = "Araya Ekle",
                Location = new Point(240, 80),
                Size = new Size(100, 30)
            };
            btnInsertAt.Click += BtnInsertAt_Click;

            Button btnRemove = new Button
            {
                Text = "Sil",
                Location = new Point(350, 80),
                Size = new Size(100, 30)
            };
            btnRemove.Click += BtnRemove_Click;

            Button btnClear = new Button
            {
                Text = "Listeyi Temizle",
                Location = new Point(460, 80),
                Size = new Size(120, 30)
            };
            btnClear.Click += BtnClear_Click;

            ListBox listBox = new ListBox
            {
                Name = "listBox",
                Location = new Point(20, 120),
                Size = new Size(560, 300)
            };

            // Kontrolleri forma ekle
            this.Controls.Add(lblData);
            this.Controls.Add(txtData);
            this.Controls.Add(lblPosition);
            this.Controls.Add(txtPosition);
            this.Controls.Add(btnAddFirst);
            this.Controls.Add(btnAddLast);
            this.Controls.Add(btnInsertAt);
            this.Controls.Add(btnRemove);
            this.Controls.Add(btnClear);
            this.Controls.Add(listBox);
        }

        private void LoadLinkedListFromDatabase()
        {
            var listBox = (ListBox)this.Controls["listBox"];
            listBox.Items.Clear();

            string query = "SELECT * FROM LinkedListNodes ORDER BY Id";
            MySqlCommand cmd = new MySqlCommand(query, connection);

            try
            {
                using (MySqlDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        listBox.Items.Add($"[ID: {reader["Id"]}] {reader["Data"]}");
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Veri yükleme hatası: {ex.Message}");
            }
        }

        private void BtnAddFirst_Click(object sender, EventArgs e)
        {
            var txtData = (TextBox)this.Controls["txtData"];
            if (string.IsNullOrWhiteSpace(txtData.Text))
            {
                MessageBox.Show("Lütfen veri giriniz.");
                return;
            }

            // Önce yeni düğümü ekle
            string insertQuery = "INSERT INTO LinkedListNodes (Data, NextId, PreviousId) VALUES (@Data, @NextId, @PreviousId); SELECT LAST_INSERT_ID();";
            MySqlCommand insertCmd = new MySqlCommand(insertQuery, connection);
            insertCmd.Parameters.AddWithValue("@Data", txtData.Text);

            // İlk düğümün ID'sini al
            int? firstNodeId = GetFirstNodeId();

            if (firstNodeId.HasValue)
            {
                // Eğer listede düğüm varsa, yeni düğümü başa ekle
                insertCmd.Parameters.AddWithValue("@NextId", firstNodeId);
                insertCmd.Parameters.AddWithValue("@PreviousId", DBNull.Value);

                int newNodeId = Convert.ToInt32(insertCmd.ExecuteScalar());

                // Eski ilk düğümün PreviousId'sini güncelle
                string updateQuery = "UPDATE LinkedListNodes SET PreviousId = @NewPreviousId WHERE Id = @Id";
                MySqlCommand updateCmd = new MySqlCommand(updateQuery, connection);
                updateCmd.Parameters.AddWithValue("@NewPreviousId", newNodeId);
                updateCmd.Parameters.AddWithValue("@Id", firstNodeId);
                updateCmd.ExecuteNonQuery();
            }
            else
            {
                // Eğer liste boşsa
                insertCmd.Parameters.AddWithValue("@NextId", DBNull.Value);
                insertCmd.Parameters.AddWithValue("@PreviousId", DBNull.Value);
                insertCmd.ExecuteNonQuery();
            }

            LoadLinkedListFromDatabase();
            txtData.Text = "";
        }

        private void BtnAddLast_Click(object sender, EventArgs e)
        {
            var txtData = (TextBox)this.Controls["txtData"];
            if (string.IsNullOrWhiteSpace(txtData.Text))
            {
                MessageBox.Show("Lütfen veri giriniz.");
                return;
            }

            // Önce yeni düğümü ekle
            string insertQuery = "INSERT INTO LinkedListNodes (Data, NextId, PreviousId) VALUES (@Data, @NextId, @PreviousId); SELECT LAST_INSERT_ID();";
            MySqlCommand insertCmd = new MySqlCommand(insertQuery, connection);
            insertCmd.Parameters.AddWithValue("@Data", txtData.Text);

            // Son düğümün ID'sini al
            int? lastNodeId = GetLastNodeId();

            if (lastNodeId.HasValue)
            {
                // Eğer listede düğüm varsa, yeni düğümü sona ekle
                insertCmd.Parameters.AddWithValue("@NextId", DBNull.Value);
                insertCmd.Parameters.AddWithValue("@PreviousId", lastNodeId);

                int newNodeId = Convert.ToInt32(insertCmd.ExecuteScalar());

                // Eski son düğümün NextId'sini güncelle
                string updateQuery = "UPDATE LinkedListNodes SET NextId = @NewNextId WHERE Id = @Id";
                MySqlCommand updateCmd = new MySqlCommand(updateQuery, connection);
                updateCmd.Parameters.AddWithValue("@NewNextId", newNodeId);
                updateCmd.Parameters.AddWithValue("@Id", lastNodeId);
                updateCmd.ExecuteNonQuery();
            }
            else
            {
                // Eğer liste boşsa
                insertCmd.Parameters.AddWithValue("@NextId", DBNull.Value);
                insertCmd.Parameters.AddWithValue("@PreviousId", DBNull.Value);
                insertCmd.ExecuteNonQuery();
            }

            LoadLinkedListFromDatabase();
            txtData.Text = "";
        }

        private void BtnInsertAt_Click(object sender, EventArgs e)
        {
            var txtData = (TextBox)this.Controls["txtData"];
            var txtPosition = (TextBox)this.Controls["txtPosition"];

            if (string.IsNullOrWhiteSpace(txtData.Text))
            {
                MessageBox.Show("Lütfen veri giriniz.");
                return;
            }

            if (!int.TryParse(txtPosition.Text, out int position) || position < 0)
            {
                MessageBox.Show("Geçersiz pozisyon. Pozisyon 0 veya daha büyük bir tam sayı olmalıdır.");
                return;
            }

            // Pozisyon 0 ise başa ekleme yap
            if (position == 0)
            {
                BtnAddFirst_Click(sender, e);
                return;
            }

            // Pozisyonu kontrol et
            int nodeCount = GetNodeCount();
            if (position > nodeCount)
            {
                MessageBox.Show($"Pozisyon listedeki eleman sayısından ({nodeCount}) büyük olamaz.");
                return;
            }

            // Pozisyon nodeCount'a eşitse sona ekleme yap
            if (position == nodeCount)
            {
                BtnAddLast_Click(sender, e);
                return;
            }

            // Araya ekleme işlemi
            int? nodeAtPositionId = GetNodeIdAtPosition(position);
            int? previousNodeId = GetPreviousNodeId(nodeAtPositionId.Value);

            // Yeni düğümü ekle
            string insertQuery = "INSERT INTO LinkedListNodes (Data, NextId, PreviousId) VALUES (@Data, @NextId, @PreviousId); SELECT LAST_INSERT_ID();";
            MySqlCommand insertCmd = new MySqlCommand(insertQuery, connection);
            insertCmd.Parameters.AddWithValue("@Data", txtData.Text);
            insertCmd.Parameters.AddWithValue("@NextId", nodeAtPositionId);
            insertCmd.Parameters.AddWithValue("@PreviousId", previousNodeId);

            int newNodeId = Convert.ToInt32(insertCmd.ExecuteScalar());

            // Önceki düğümün NextId'sini güncelle
            if (previousNodeId.HasValue)
            {
                string updatePrevQuery = "UPDATE LinkedListNodes SET NextId = @NewNextId WHERE Id = @Id";
                MySqlCommand updatePrevCmd = new MySqlCommand(updatePrevQuery, connection);
                updatePrevCmd.Parameters.AddWithValue("@NewNextId", newNodeId);
                updatePrevCmd.Parameters.AddWithValue("@Id", previousNodeId);
                updatePrevCmd.ExecuteNonQuery();
            }

            // Sonraki düğümün PreviousId'sini güncelle
            string updateNextQuery = "UPDATE LinkedListNodes SET PreviousId = @NewPreviousId WHERE Id = @Id";
            MySqlCommand updateNextCmd = new MySqlCommand(updateNextQuery, connection);
            updateNextCmd.Parameters.AddWithValue("@NewPreviousId", newNodeId);
            updateNextCmd.Parameters.AddWithValue("@Id", nodeAtPositionId);
            updateNextCmd.ExecuteNonQuery();

            LoadLinkedListFromDatabase();
            txtData.Text = "";
        }

        private void BtnRemove_Click(object sender, EventArgs e)
        {
            var listBox = (ListBox)this.Controls["listBox"];
            if (listBox.SelectedIndex == -1)
            {
                MessageBox.Show("Lütfen silmek için bir öğe seçin.");
                return;
            }

            // Seçilen öğenin ID'sini al
            string selectedItem = listBox.SelectedItem.ToString();
            int startIndex = selectedItem.IndexOf("ID: ") + 4;
            int endIndex = selectedItem.IndexOf("]");
            string idStr = selectedItem.Substring(startIndex, endIndex - startIndex);
            int idToRemove = int.Parse(idStr);

            // Silinecek düğümün NextId ve PreviousId değerlerini al
            string selectQuery = "SELECT NextId, PreviousId FROM LinkedListNodes WHERE Id = @Id";
            MySqlCommand selectCmd = new MySqlCommand(selectQuery, connection);
            selectCmd.Parameters.AddWithValue("@Id", idToRemove);

            int? nextId = null;
            int? previousId = null;

            using (MySqlDataReader reader = selectCmd.ExecuteReader())
            {
                if (reader.Read())
                {
                    nextId = reader["NextId"] as int?;
                    previousId = reader["PreviousId"] as int?;
                }
            }

            // Önceki ve sonraki düğümleri birbirine bağla
            if (previousId.HasValue && nextId.HasValue)
            {
                // Ortadaki düğümü silme
                string updatePrevQuery = "UPDATE LinkedListNodes SET NextId = @NewNextId WHERE Id = @Id";
                MySqlCommand updatePrevCmd = new MySqlCommand(updatePrevQuery, connection);
                updatePrevCmd.Parameters.AddWithValue("@NewNextId", nextId);
                updatePrevCmd.Parameters.AddWithValue("@Id", previousId);
                updatePrevCmd.ExecuteNonQuery();

                string updateNextQuery = "UPDATE LinkedListNodes SET PreviousId = @NewPreviousId WHERE Id = @Id";
                MySqlCommand updateNextCmd = new MySqlCommand(updateNextQuery, connection);
                updateNextCmd.Parameters.AddWithValue("@NewPreviousId", previousId);
                updateNextCmd.Parameters.AddWithValue("@Id", nextId);
                updateNextCmd.ExecuteNonQuery();
            }
            else if (previousId.HasValue)
            {
                // Son düğümü silme
                string updateQuery = "UPDATE LinkedListNodes SET NextId = NULL WHERE Id = @Id";
                MySqlCommand updateCmd = new MySqlCommand(updateQuery, connection);
                updateCmd.Parameters.AddWithValue("@Id", previousId);
                updateCmd.ExecuteNonQuery();
            }
            else if (nextId.HasValue)
            {
                // İlk düğümü silme
                string updateQuery = "UPDATE LinkedListNodes SET PreviousId = NULL WHERE Id = @Id";
                MySqlCommand updateCmd = new MySqlCommand(updateQuery, connection);
                updateCmd.Parameters.AddWithValue("@Id", nextId);
                updateCmd.ExecuteNonQuery();
            }

            // Düğümü sil
            string deleteQuery = "DELETE FROM LinkedListNodes WHERE Id = @Id";
            MySqlCommand deleteCmd = new MySqlCommand(deleteQuery, connection);
            deleteCmd.Parameters.AddWithValue("@Id", idToRemove);
            deleteCmd.ExecuteNonQuery();

            LoadLinkedListFromDatabase();
        }

        private void BtnClear_Click(object sender, EventArgs e)
        {
            DialogResult result = MessageBox.Show("Tüm listeyi silmek istediğinize emin misiniz?", "Onay", MessageBoxButtons.YesNo);
            if (result == DialogResult.Yes)
            {
                string query = "DELETE FROM LinkedListNodes";
                MySqlCommand cmd = new MySqlCommand(query, connection);
                cmd.ExecuteNonQuery();
                LoadLinkedListFromDatabase();
            }
        }

        // Yardımcı metodlar
        private int? GetFirstNodeId()
        {
            string query = "SELECT Id FROM LinkedListNodes WHERE PreviousId IS NULL LIMIT 1";
            MySqlCommand cmd = new MySqlCommand(query, connection);
            object result = cmd.ExecuteScalar();
            return result != null ? Convert.ToInt32(result) : (int?)null;
        }

        private int? GetLastNodeId()
        {
            string query = "SELECT Id FROM LinkedListNodes WHERE NextId IS NULL LIMIT 1";
            MySqlCommand cmd = new MySqlCommand(query, connection);
            object result = cmd.ExecuteScalar();
            return result != null ? Convert.ToInt32(result) : (int?)null;
        }

        private int GetNodeCount()
        {
            string query = "SELECT COUNT(*) FROM LinkedListNodes";
            MySqlCommand cmd = new MySqlCommand(query, connection);
            return Convert.ToInt32(cmd.ExecuteScalar());
        }

        private int? GetNodeIdAtPosition(int position)
        {
            // İlk düğümü bul
            int? currentNodeId = GetFirstNodeId();
            if (!currentNodeId.HasValue) return null;

            // Pozisyona kadar ilerle
            for (int i = 0; i < position; i++)
            {
                string query = "SELECT NextId FROM LinkedListNodes WHERE Id = @Id";
                MySqlCommand cmd = new MySqlCommand(query, connection);
                cmd.Parameters.AddWithValue("@Id", currentNodeId);
                object result = cmd.ExecuteScalar();
                if (result == null || result == DBNull.Value) return null;
                currentNodeId = Convert.ToInt32(result);
            }

            return currentNodeId;
        }

        private int? GetPreviousNodeId(int nodeId)
        {
            string query = "SELECT PreviousId FROM LinkedListNodes WHERE Id = @Id";
            MySqlCommand cmd = new MySqlCommand(query, connection);
            cmd.Parameters.AddWithValue("@Id", nodeId);
            object result = cmd.ExecuteScalar();
            return result != null && result != DBNull.Value ? Convert.ToInt32(result) : (int?)null;
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);
            if (connection != null && connection.State == ConnectionState.Open)
            {
                connection.Close();
            }
        }
    }  
}
Osman Bayrak
Osman Bayrak

Yazılım Mühendisiyim. Teknoloji ve yazılıma meraklıyım.

Articles: 334