"Aplikacja formularzy Windows" w C# i zmienne i stałe w kilku plikach .cs

0

Witam kolegów (i koleżanki :))) )

Próbuję powoli pisać coś w C# z pomocą wielu poradników i z pomocą forumowiczów. Mam taki dość podstawowy problem. Chcę od początku trzymać "porządek" w kodzie i żeby program miał "ręce i nogi" i był później łatwy w rozbudowie dlatego staram się dzielić różne tematy na osobne pliki cs - np. mam główny plik z programem i tradycyjnie Form1.cs. Dodatkowo dodałem sobie nowy plik i nazwałem go "Baza.cs" - tak trzymam dwie klasy - jedną z konfiguracją połączenia do bazy, drugą z zapytaniami do bazy. Sama aplikacja jest dość prosta - mam dwa DataGridView, dwa buttony i jeden TextBox. Po naciśnięciu przycisków wywołuje połączenie z bazą i zapytanie (skonfigurowane w pliku Baza.cs) i wynik wyświetlam w odpowiednim DataGridView (dwa buttony, dwa zapytania, dwa DataGridView). Chciałbym po drodze wprowadzić dane do TextBox i wykorzystać je w zapytaniu jako warunek zapytania i tu pojawia się problem - mogę wykonać textBox1.Text w obszarze w którym definiuję działanie po kliknięciu przycisku (np public void button1_Click(object sender, EventArgs e)) natomiast nie jestem w stanie w pliku Baza.cs w klasach w których mam zdefiniowane połączenie i zapytania wywołać textBox1.Text.
Przypuszczam że problem leży po stronie właściwego umiejscowienia w konstruktorze/klasie - czy ktoś z kolegów może coś doradzić w tym temacie gdzie szukać błędu? Szczerze to mam problem ze ogarnięciem tematu totalnych podstaw na zasadzie klasa/kontruktor - może ktoś zna jakiś skuteczny szybki poradnik/kurs w tym temacie?

1

Dodać odpowiednią funkcje do klasy baza dzięki której będziesz mógł na niej wykonać akcje/zapytanie. Utworzyć pole prywatne tej klasy(baza) w klasie Form1, a nastąpienie wywołać tę funkcje(do akcji/zapytania) w zdarzeniu przekazując jej jako parametr zawartość TextBox.Text.

0

Dzięki - zrobiłem tak jak piszesz i ten problem już mi się rozwiązał ale pojawił się inny.
Dla jasności trochę kodu:
Plik Baza.cs (fragment):

 
class BazaZapytania
    {
        public static string nrKlienta;
        public static string Zap1 = "select * from Tabela1 WHERE Odbiorca=" + Convert.ToInt32(nrKlienta);
        public static string Zap2 = "select * from Tabela2 WHERE Dostawca=" + Convert.ToInt32(nrKlienta);
    }

Plik Form1.cs (także fragment):

 
public void button1_Click(object sender, EventArgs e)
        {
            if (tbNrKlienta.TextLength == 0)
            {
                MessageBox.Show("Wprowadź numer klienta");
            }
            else
            {
                Baza.Centrala1.Open();
                BazaZapytania.nrKlienta = tbNrKlienta.Text;
                label3.Text = tbNrKlienta.Text;
                OdbcDataAdapter daneZap1 = new OdbcDataAdapter(BazaZapytania.Zap1, Baza.Centrala1);
                OdbcCommandBuilder builderZap1 = new OdbcCommandBuilder(daneZap1);
                DataSet dsZap1 = new DataSet();
                daneZap1.Fill(dsZap1, "Tabela1");
                dtGrid1.DataSource = dsZap1.Tables["Tabela1"];
                Baza.Centrala1.Close();
            }
        }

Po drodze mamy konwersję string do int32 i tutaj pojawia się problem - do mojego zapytanie trafia 0 mimo wprowadzonych danych w tbNrKlienta (TextBox).
Próbowałem zdefiniować nrKlienta jako int i wykonywać konwersję:

 BazaZapytania.nrKlienta = Convert.ToInt32(tbNrKlienta.Text);
  • efekt taki sam, do zapytania trafiało 0.
    Gdzie tkwi mój błąd??
    Oczywiście wprowadzam liczby na zasadzie np 102938
0

Nie wiem, czy to może być przyczyną, ale po co zamieniać stringa nrKlienta na inta, skoro ma być tylko dodany do innego stringa?

0

Jeśli tej zamiany nie wykonam to wtedy program się "wywala" bo nrKlienta jest przekazywany do zapytania jako puste pole i zamiast "WHERE Odbiorca=0" tak jak to ma miejsce w przypadku konwersji warunek zapytania ma postać "WHERE Odbiorca= "
W oby przypadkach jest źle bo jak podaję w TextBox np 101267 i robię z tego Convert.ToInt32 to wtedy mam "WHERE Odbiorca=0" a powinno być "WHERE Odbiorca=101267" a jak nie zrobię konwersji czyli wszytko jako string to mam "WHERE Odbiorca= "

1

Sprawdź jaką wartość ma zmienna nrKlienta po wykonaniu tej linijki.

BazaZapytania.nrKlienta = tbNrKlienta.Text;

Możesz robić to tak, jeżeli nie jesteś zmuszony używać zmiennych statycznych to nie rób tego. W ogóle wszystkie zapytania wraz z bazą powinieneś sobie fajnie w klasy opakować aby nie tworzyć połączenia w zdarzeniu.

class BazaZapytan
{
    public static string GetByOdbiorca(int id)
    {
        return string.Format(@"select * from Tabela1 WHERE Odbiorca={0}", id);
    }

    public static string GetByDostawca(int id)
    {
        return string.Format(@"select * from Tabela2 WHERE Dostawca={0}", id);
    }
}

dodanie znacznika <code class="csharp"> - fp

1

To jeszcze inaczej. Wydaje mi się, że statici są inicjalizowane przy uruchomieniu programu. Czyli Po uruchomieniu programu nrKlienta jest pusty, zas zapytania dostają wartość z wykorzystaniem właśnie tego pustego stringa. Aby tego uniknąc powinieneś chyba zrobić osobną statyczną funkcję na stworzenie zapytania. np.:

class BazaZapytania
    {
        public static string nrKlienta;
        public static string Zap1, Zap2;
        public static void StworzZapytania(string nrKlienta)
        {
             Zap1 = "select * from Tabela1 WHERE Odbiorca=" + nrKlienta;
             Zap2 = "select * from Tabela2 WHERE Dostawca=" + nrKlienta;
        }
    }

nrKlienta przekazuje oczywiście przez argument funckji. Do Zap1 i Zap2 powinny teraz zostać poprawnie przypisane zapytania. Pisze do z głowy bez sprawdzania, wiec mogłem coś pomieszać, ale chyba powinno działać.

usunięcie pustych linii ze znacznika <code> - fp

0
Bumcykowy napisał(a):

Sprawdź jaką wartość ma zmienna nrKlienta po wykonaniu tej linijki.

BazaZapytania.nrKlienta = tbNrKlienta.Text;

Możesz robić to tak, jeżeli nie jesteś zmuszony używać zmiennych statycznych to nie rób tego. W ogóle wszystkie zapytania wraz z bazą powinieneś sobie fajnie w klasy opakować aby nie tworzyć połączenia w zdarzeniu.

class BazaZapytan
{
    public static string GetByOdbiorca(int id)
    {
        return string.Format(@"select * from Tabela1 WHERE Odbiorca={0}", id);
    }

    public static string GetByDostawca(int id)
    {
        return string.Format(@"select * from Tabela2 WHERE Dostawca={0}", id);
    }
}

dodanie znacznika <code class="csharp"> - fp

No właśnie chciałbym unikać połączeń w zdarzeniach itd. Najlepiej gdybym mógł w klasach (w osobnym pliku) przygotować wszystkie zapytania, później stworzyć np metodę która nawiązywałaby połączenie i wykonywała zapytanie a później w zdarzeniu odwołać się do tej metody podając jako argument które zapytanie ma wykonać, jaki jest parametr i gdzie ma wyświetlić jego wynik. Czy mój tok myślenia jest poprawny? Po raz kolejny zaznaczam że zaczynam "przygodę" z C# i jeśli napisałem jakieś "bzdury" to sorry ale tak jak każdy kiedyś - uczę się. Chcę uniknąć niepotrzebnego "namnażania" kodu i jeśli jest jakaś czynność która np różni się tylko zapytaniem sql i nazwą parametru (typ parametru ten sam dla każdego zapytania) to czy mogę zrobić jeden "wzorzec" i później tylko się do niego odwoływać podając nowe argumenty i parametry? Czego najlepiej użyć w tym przypadku - metody ?
Użyłem zmienną statyczną dlatego że jeśli nie była jako statyczna to kompilator nie pozwalał jej użyć. Wartość tbNrKlienta.Text jest prawidłowa - taka jak wprowadziłem ale pewnie tak jak napisano statyk powoduje że w momencie uruchamiania programu jest 0 i ono już pozostaje.

0

Poszukałem, poczytałem i jestem na dobrej drodze :)) Zrobiłem w klasie konstruktor w którym mam zdefiniowane połączenie z bazą, zapytanie, parametr itd - w zdarzeniu kliknięcia buttona tworzę odwołanie do tego konstruktora i przekazuję potrzebne dane i .... działa :))
Dzięki za wszelkie sugestie i pomoc - małymi kroczkami coraz bardziej zaczynam "ogarniać" programowanie w C# :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1