Dynamiczne wyszukiwanie w bazie
Niedawno zacząłem się zastanawiać nad możliwością dynamicznego przeszukiwania bazy danych w programach pisanych w C#. Chodziło o to aby podczas wpisywania kolejnych liter do pola tekstowego były pobierane wszystkie rekordy zawierające w odpowiednim polu wpisany ciąg znaków. Udało się to zrealizować już w pierwszym testowym programie.
Sposób, który wybrałem polega na wysyłaniu nowego zapytania SQL do bazy za każdym razem kiedy występuje zdarzenie TextChanged kontrolki TextBox.
Z pierwszych testów wynika, że przy bazie lokalnej (Postgressql zainstalowany na tym samym komputerze co uruchamiany program) nie występuje żadne dostrzegalne opóźnienie. Prawdopodobnie sytuacja nie powinna się zmienić przy bazie w sieci lokalnej, co jest sytuacją wystarczającą jeśli chodzi o projekty, w których zamierzam wykorzystać tą technikę. Ale ten scenariusz zapewne zbadam dogłębniej innym razem.
Jak już wspomniałem wykorzystuję relacyjną bazę danych Posgressqsl. Do łączenia się z tą bazą z poziomu c# używam biblioteki Npgsql2 (download).
Poniżej kod z pliku Form1.cs, reszta projektu to kod wygenerowany przez Visual Studio dlatego nie jest tutaj zamieszczony:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Npgsql;
namespace LiveSearchTest1
{
public partial class Form1 : Form
{
NpgsqlConnection conn; //obiekt reprezentujący połącznie do bazy
public Form1()
{
InitializeComponent();
conn = new NpgsqlConnection("server=127.0.0.1;Port=5432;User Id=postgres;Password=haslo;Database=postgres;"); // połączenie z bazą danych
conn.Open();
Szukaj();
}
private void textBox1_TextChanged(object sender, EventArgs e) //funkcja obsługująca zdarzenie zmiany tekstu w TextBoxie
{
Szukaj();
}
void Szukaj()
{
NpgsqlCommand command; // obiekt reprezentujący jedno zapytanie do bazy
command = new NpgsqlCommand("SELECT * FROM testowa_1 WHERE tekst LIKE '%" + textBox1.Text + "%'", conn); // zapytanie sql pobierające z tabeli testowa_1 wszystkie rekordy
//zawierające w dowolnym miejscu pola 'tekst' ciąg wpisany w TextBoxie
NpgsqlDataReader dr = command.ExecuteReader();
listView1.Items.Clear();
int i = 0;
while (dr.Read())
{
listView1.Items.Add(dr[0].ToString()).SubItems.Add(dr[1].ToString());
i++;
}
label1.Text = i.ToString(); //label1 wyświetla liczbę znalezionych rekordów
}
}
}
Nazwy kontrolek pozostawiłem domyślne żeby nie musieć dodatkowo wyjaśniać co dana nazwa reprezentuje.
Na zakończenie
Sposób który tutaj zaprezentowałem jest moim osobistym wymysłem i na pewno ma wadę w postaci dużej liczby zapytać wysyłanych do bazy. W przypadku gdy tylko jeden program łączy się z bazą i pobiera dane tylko z jednej tabeli wszystko działa OK, jednak na pewno sprawdzę jak sprawa będzie się miała gdy programów i tabel będzie kilka i będą się łączyć z bazą w sieci lokalnej, a nie na localhoście. Jeżeli ktoś zna lepszy sposób na rozwiązanie tytułowej kwestii to oczywiście zachęcam do podzielenia się nim w komentarzach.



Leave a Comment