C# zapis danych do SQL

0

Hej,
w poprzednim temacie koledzy pomogli mi podzielić dane na częsci, które mają być umieszczone każdy w osobnej kolumnie tabeli SQL.
Względem poprzedniego tematu mam stworzoną aplikacje okienkową z dwoma buttonami.
Jeden importuje dane z plik .txt , dzieli je na części i zapisuje w tablicy.
Drugi ma za zadanie połączyć się z bazą danych (i to mam zrobione) i docelowo zczytać dane z utworzonej przez button1 tablicy z podzielonymi danymi i wpisać je w odpowiednie kolumny w tabeli SQL.
Napotkałem jednak problemy, nie potrafię odwołać się do tych danych w tablicy i użyć ich do wpisania w kolumny.
Część kodu, która odpowiedzialna jest za podział:

 private void button1_Click(object sender, EventArgs e)
        {
            var lines = File.ReadAllLines(@"U:\Users\XXX\Desktop\Rej.txt");
            var builder = new StringBuilder();

            for (int i = 0; i < lines.Length; i++)
            {
                builder.Append(lines[i].Substring(0, 5)).Append(' ').Append(lines[i].Substring(5, 14))
                    .Append(' ').Append(lines[i].Substring(19, 2)).Append(' ').Append(lines[i][lines[i].Length - 2])
                    .Append(' ').Append(lines[i][lines[i].Length - 1]);
                lines[i] = builder.ToString();
                builder.Clear();
                File.WriteAllLines(@"U:\Users\XXX\Desktop\test2xzx3.txt", lines);
                
            }
        }

Kod drugiego buttona, który jak na razie łączy się z bazą:

  private void button2_Click(object sender, EventArgs e)
        {
            
             using (SqlConnection conn = new SqlConnection())
             {
                string connString = @"Server=XXX\SQLEXPRESS;Database=rcp;Integrated Security=SSPI";
                 if (conn.State == ConnectionState.Closed)
                 {
                     conn.ConnectionString = connString;
                     try
                     {
                         conn.Open();
                         MessageBox.Show("Succsessfull DB Connnection", "DB Connection Test", MessageBoxButtons.OK, MessageBoxIcon.Information);

                     }
                     catch (Exception ex)
                     {
                         MessageBox.Show("Invalid DB SqlConnnection" + Environment.NewLine + ex.Message, "DB Connection Test", MessageBoxButtons.OK, MessageBoxIcon.Error);
                     }
                 }
        }

        }

Częsciowy kod, który próbuje dodać do buttona2.

  private void button2_Click(object sender, EventArgs e)
        {
            
             using (SqlConnection conn = new SqlConnection())
             {
                string connString = @"Server=XXX\SQLEXPRESS;Database=rcp;Integrated Security=SSPI";
                 if (conn.State == ConnectionState.Closed)
                 {
                     conn.ConnectionString = connString;
                     try
                     {
                         conn.Open();
                         MessageBox.Show("Succsessfull DB Connnection", "DB Connection Test", MessageBoxButtons.OK, MessageBoxIcon.Information);

                         if(conn.State == ConnectionState.Open)
                         {
                             try
                             {
                                 using (SqlCommand SQLcommand = new SqlCommand(
                                     "INSERT INTO dbo.ODCZYTY VALUES(@numer_karty, @data, @rodzaj, @obszar, @kierunek)", conn))
                                 {
                                     SQLcommand.Parameters.AddWithValue("numer_karty",);
                                 }
                             }
                         }
                     }
                     catch (Exception ex)
                     {
                         MessageBox.Show("Invalid DB SqlConnnection" + Environment.NewLine + ex.Message, "DB Connection Test", MessageBoxButtons.OK, MessageBoxIcon.Error);
                     }
                 }
        }

        }

I teraz mam jeszcze pytanie, czy kod zawarty w warunku if dotyczący dodania danych do kolumn w tabeli SQL jest prawidłowy(wiem, że nie skończony),ale czy idę chociaż w dobrą stronę?

0

Trochę namieszałeś. Napisz sobie osobną klasę, która będzie Ci realizować cała komunikację z bazą danych i później używaj tylko jej metod. Będziesz miał dużo prościej. No i tych try za dużo. Za dużo rzeczy chcesz osiągnąć na raz.

  • łącz się z bazą;
  • wykonuj zapytanie (jeśli masz kilka kwerend do wykonania - zepnij je w jedną transakcję);
  • rozłącz się.

Czyli co najmniej trzy metody masz do wykonania. Zrób to w tej klasie do obsługi bazy. Wtedy w tym buttonie kod skróci się do 3 - 5 linijek.

0

Ok, zrobiłem tak:

public void podzial()
        {
            var lines = File.ReadAllLines(@"U:\Users\XXX\Desktop\Rej.txt");
            var builder = new StringBuilder();

            for (int i = 0; i < lines.Length; i++)
            {
                builder.Append(lines[i].Substring(0, 5)).Append(' ').Append(lines[i].Substring(5, 14))
                    .Append(' ').Append(lines[i].Substring(19, 2)).Append(' ').Append(lines[i][lines[i].Length - 2])
                    .Append(' ').Append(lines[i][lines[i].Length - 1]);
                lines[i] = builder.ToString();
                builder.Clear();
                File.WriteAllLines(@"U:\Users\XXX\Desktop\test2xzx3.txt", lines);

            }
        }

        public void SQLConnection()
        {
            using (SqlConnection conn = new SqlConnection())
            {
                string connString = @"Server=XXX\SQLEXPRESS;Database=rcp;Integrated Security=SSPI";
            if (conn.State == ConnectionState.Closed)
            {
                conn.ConnectionString = connString;
                try
                {
                    conn.Open();
                    MessageBox.Show("Succsessfull DB Connnection", "DB Connection Test", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Invalid DB SqlConnnection" + Environment.NewLine + ex.Message, "DB Connection Test", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
    }

I użycie w buttonach:

 private void button1_Click(object sender, EventArgs e)
        {
            podzial();
        }

        private void button2_Click(object sender, EventArgs e)
        {

            SQLConnection();

        }

Czy tak może zostać?

3

Zrób klasę do zarządzania tym SQL'em:

Pseudokod:

public class DataBase {

	// Connector, którego używa klasa.
	private SqlConnection _connection;

	// Inicjalizacja danych do połączenia. Tutaj podajesz jakie rzeczy jak nazwa db, login etc..
	public void Initialize(/* connect string data */);

	// Jeżeli ta metoda zwróci `true` to połączenie jest Ok i można wykonać zapytanie;
	public bool Connect();

	// Jeżeli ta metoda zwróci `true` to insert wykonał się prawidłowo (tak samo update i delete)
	// W przypadku selecta zwracasz nie `bool` tylko wynik zapytania albo np. `null`
	public bool Insert(/* data */);

	// Jeżeli ta metoda zwróci `true` to jesteś prawidłowo rozłączony; Ewentualnie `void` - patrz niżej.
	public bool Disconnect();
}

public bool Connect(); możesz wykorzystać na zewnątrz klasy sprawdzając np. w GUI czy ustawienie connect-stringa przebiegło prawidłowo. Możesz też jej użyć prywatnie w metodzie public bool Insert():

public bool Insert(){
	try{
		if(this.Connect()){
			// Insert się wykonał. (są różne metody sprawdzenia, zwykle jest to zmienna, która przechowuje tzw. `RowAffected`)
			this.Disconnect(); // ta funkcje może zwracać `void` - ewentualne błędy wyłapie `try - catch`.
			return (RowAffected > 0) ? true : false;
		}
		return false;
	}
	catch(Exception){
		// Tutaj możesz połapać komunikat z wyjątku.
		return false;
	}
}

I teraz w GUI:

// this._db to np. prywatna instancja Twojej klasy do bazy danych
if(this._db.Insert(/* some data */)) MessageBox.Show("GOOD!");

Nie musisz łapać komunikatu dla false, bo to zrobi za Ciebie wyjątek, jeżeli zdecydujesz się na połapanie tego co wywala Exception.

3

zmień tego potworka

builder.Append(lines[i].Substring(0, 5)).Append(' ').Append(lines[i].Substring(5, 14))
                    .Append(' ').Append(lines[i].Substring(19, 2)).Append(' ').Append(lines[i][lines[i].Length - 2])
                    .Append(' ').Append(lines[i][lines[i].Length - 1]);

na

var line = lines[i];
builder.AppendFormat(
    "{0} {1} {2} {3} {4}", 
    line.Substring(0, 5), 
    line.Substring(5, 14), 
    line.Substring(19, 2), 
    line[line.Length - 2]), 
    line[line.Length - 1]
);

public void SQLConnection() - jeśli się nie udało podłączyć, to złap wyjątek, coś tam wypisz i jedź dalej. Nieważne, że nie udało się połączyć z bazą. Wyjątek nie jest rzucany dalej, nie jest nawet zwracany żaden magic value typu false. Wyjątek w końcu poleci, a jakże, ale nie z miejsca, gdzie łączysz się z bazą, a z pierwszego, które z połączenia będzie chciało skorzystać. Tym samym podstawiasz sobie nogę.

0

Chłopaki to nie daje mi spokoju i jeśli znalazłem takie osoby jak wy, które dzielą się wiedzą to chce to wykorzystać i poznać to co mogę.
Ok, tworzę klasę dla SQL, ale po kolei:

public class DataBase {
 
    // Connector, którego używa klasa.

 

Co mam rozumieć przez słowo "Connector"? Bo naprawdę nie wiem co tam mam umieścić.
Czy ta druga metoda ma wyglądać tak:

 // Inicjalizacja danych do połączenia. Tutaj podajesz jakie rzeczy jak nazwa db, login etc..	
    public void Initialize(this._connection)
	{
	
                string this._connection= @"Server=XXX\SQLEXPRESS;Database=rcp;Integrated Security=SSPI";
			
	}
   public bool Connect()
	{
                conn.ConnectionString = this._connection;
		conn.Open();
	}
    // Jeżeli ta metoda zwróci `true` to insert wykonał się prawidłowo (tak samo update i delete)
    // W przypadku selecta zwracasz nie `bool` tylko wynik zapytania albo np. `null`
    public bool Insert(/* data */);
 
    // Jeżeli ta metoda zwróci `true` to jesteś prawidłowo rozłączony;
    public bool Disconnect()
	{
                disconn.ConnectionString = this._connection;
		disconn.Close();
	}

Dodałem również klasę podziału łańcucha:

 
public class Podzial 
{
public void podzial()
        {
            var lines = File.ReadAllLines(@"U:\Users\XXX\Desktop\Rej.txt");
            var builder = new StringBuilder();
 
            for (int i = 0; i < lines.Length; i++)
            {
                builder.Append(lines[i].Substring(0, 5)).Append(' ').Append(lines[i].Substring(5, 14))
                    .Append(' ').Append(lines[i].Substring(19, 2)).Append(' ').Append(lines[i][lines[i].Length - 2])
                    .Append(' ').Append(lines[i][lines[i].Length - 1]);
                lines[i] = builder.ToString();
                builder.Clear();
                File.WriteAllLines(@"U:\Users\XXX\Desktop\test2xzx3.txt", lines);
 
            }
        }
}

Wiem, że są to podstawowe dane, ale chce ich się nauczyć od praktyków, więc proszę o w miarę łagodne epitety względem mnie:)

0

public void Initialize(this._connection) - ??? Próbowałeś to skompilować chociaż?

Podział - zajebista nazwa klasy, kolejną nazwij Zjednoczenie.
Używaj ANGIELSKICH nazw, ponadto formułuj je w takim sposób, żeby coś mówiły o tym, co klasa/metoda robi. A ani Twoja klasa, ani metoda niczego nie dzieli; metoda przetwarza stringa, a klasa to taka namiastka serwisu albo helpera.
Zawartość metody podzial() olewa moje wskazówki z poprzedniego posta, jest nieczytelna.
Używanie StringBuildera do zbudowania jednej linijki jest nieoptymalne. Połącz to z tym, co wcześniej pisałem i użyj string.Format.

Robienie klasy na connector, który robi dokładnie to samo, co SqlConnection, ma sens tylko wtedy, jeśli przewidywane jest używanie połączeń do innych typów baz danych. Ewentualnie może pomóc w pisaniu testów na mockach. Żadne z tych nie ma to tutaj miejsca.

0
ŁF napisał(a):

public void Initialize(this._connection) - ??? Próbowałeś to skompilować chociaż?

Wiem, to już ogarnąłem.
Co do nazw to są one dla mnie, na razie chce ogarnąć, żeby to działało a później zajmę sie takimi rzeczami.
Tworząc wszystko w tych klasach nie mogę tego użyć w buttonie.

public class Podzial 
{
        public void podzial()
        {
            var lines = File.ReadAllLines(@"U:\Users\XXX\Desktop\Rej.txt");
            var builder = new StringBuilder();
 
            for (int i = 0; i < lines.Length; i++)
            {
                var line = lines[i];
				builder.AppendFormat(
					"{0} {1} {2} {3} {4}", 
					line.Substring(0, 5), 
					line.Substring(5, 14), 
					line.Substring(19, 2), 
					line[line.Length - 2]), 
					line[line.Length - 1]
				);
                lines[i] = builder.ToString();
                builder.Clear();
                File.WriteAllLines(@"U:\Users\XXX\Desktop\test2xzx3.txt", lines);
 
            }
        }
} 
0
CodeObiect napisał(a):

Tworząc wszystko w tych klasach nie mogę tego użyć w buttonie.

Niby dlaczego?

0

No bo np. po stworzeniu klasy odpowiadające za przetworzenie łańcucha znaków (moja nazwa Podział) i towrząc button nie mogę w nim użyć danej metody podział.

0

Chrzanisz waść. Abstrahując od tego jak to idiotycznie wygląda - new Podzial().podzial();. I nie "tworząc button", tylko "w metodzie wywoływanej w obsłudze kliknięcia na buttonie".

0

Czepiasz się nazw i określeń. Nie siedzę w programowaniu 5 lat, żeby dobrze określić wszystkie czynności.
Dlaczego chrzanie? Widocznie nie potrafię użyć tych metod.

0

Dlatego dostajesz wskazówki. Burzysz się, że Cię uczę poprawnych sformułowań i nazewnictwa, wiesz, nazywaj sobie wszystko po swojemu, ale za kilka-kilkanaście lat i tak będziesz robić po mojemu. A czy wcześniej czy później to kwestia tego, czy będziesz umiał posłuchać trafnych uwag. Zapamiętaj na zawsze, że nazewnictwo to jedna z najważniejszych rzeczy w programowaniu.

Czemu twierdzę, że chrzanisz? Napisałeś "nie mogę w nim użyć danej metody podział". Co to znaczy "nie mogę"? Ktoś Ci zabronił? Tworzysz sobie instancję klasy tam, gdzie potrzebujesz, a potem tam gdzie potrzebujesz korzystasz z niej. Może to na przykład być zmienna lokalna var podział = new Podzial();, tworzona w tym Twoim guziku i tamże wykorzystywana: podział.podzial();.

0

W sumie masz racje. Dzięki za cenną rade!

Co do drugiej części. Nie wiem czy dobrze rozumiem, spójrz na kod:

 public class Proccesing
    {
        public void processingString()
        {
            var lines = File.ReadAllLines(@"U:\Users\XXX\Desktop\Rej.txt");
            var builder = new StringBuilder();

            for (int i = 0; i < lines.Length; i++)
            {
                var line = lines[i];
                builder.AppendFormat(
                    "{0} {1} {2} {3} {4}",
                    line.Substring(0, 5),
                    line.Substring(5, 14),
                    line.Substring(19, 2),
                    line[line.Length - 2]), 
                    line[line.Length - 1]
                );
            lines[i] = builder.ToString();
            builder.Clear();
            File.WriteAllLines(@"U:\Users\XXX\Desktop\test2xzx3.txt", lines);
        }
    }
private void button1_Click(object sender, EventArgs e) 
        {
            var processingString = new Processing();
            
        }

I jak próbuje zrobić

processingString.Processing();

to po kropce nie mam do wyboru Processing.

2

Klasę nazwij ProcessingService.
Metodę nazwij ProcessFile (publiczne elementy zawsze camel case z dużej litery na początku). Nie ProcessString, bo procesujesz w tej metodzie plik. Plik co prawda zawiera stringi, ale przetwarzasz plik. Idealnie byłoby rozbić metodę na dwie - publiczną ProcessFile i prywatną ProcessString.

W obsłudze kliknięcia daj

var processingService = new ProcessingService();
processingService.ProcessFile();

Dobrze by było podawać ścieżkę do pliku w argumencie metody ProcessFile, ale może nie wszystko naraz...

0

Poprawiłem wedle Twoich wskazówek.
W kodzie zaznaczyłem komentarzami błędy, gdzie je podkreśla.

  for (int i = 0; i < lines.Length; i++)
            {
                var line = lines[i];
                builder.AppendFormat(
                    "{0} {1} {2} {3} {4}",
                    line.Substring(0, 5),
                    line.Substring(5, 14),
                    line.Substring(19, 2),
                    line[line.Length - 2]), // w tym miejscu po przecinku podkreśla mi błąd
                    line[line.Length - 1]
                ); // tu też 
            lines[i] = builder.ToString(); // i podkreśla mi też i
            builder.Clear();
            File.WriteAllLines(@"U:\Users\XXX\Desktop\test2xzx3.txt", lines);
        }
0

Ok, to mi ładnie działa :)
Patrząc na klasę DataBase, powiedz mi czy connect i disconnect jest źle?

     public class DataBase
    {
        private SqlConnection _connection;
    
        public void Initialize()
        {
            
            string connString = @"Server=XXX\SQLEXPRESS;Database=rcp;Integrated Security=SSPI";
            _connection.ConnectionString = connString;
        }
        public bool Connect()
        {
              this._connection.Open();
              return true;
        }
        // Jeżeli ta metoda zwróci `true` to insert wykonał się prawidłowo (tak samo update i delete)
        // W przypadku selecta zwracasz nie `bool` tylko wynik zapytania albo np. `null`
        //public bool Insert(/* data */);

        // Jeżeli ta metoda zwróci `true` to jesteś prawidłowo rozłączony;
        public bool Disconnect()
        {
            this._connection.Close();
            return true;
            
        }
    }

Czy czasami to nie ma być w guziku, tak jak przy metodzie ProcessFile ?

 _connection.ConnectionString = connString;
0
CodeObiect napisał(a):

Ok, to mi ładnie działa :)
Patrząc na klasę DataBase, powiedz mi czy connect i disconnect jest źle?

Tak. Na jakiej podstawie zwracasz zawsze true?

0

Connect/Disconnect - po co cokolwiek zwracają, skoro zawsze zwracają to samo?
Zwracanie negatywnej wartości w momencie, kiedy coś się nie powiodło, jest słabe. Łatwo zapomnieć sprawdzić status operacji, a potem pojawiają się dziwne błędy w dziwnych miejscach. Prościej rzucić wyjątkiem (co akurat - przypadkiem - u Ciebie się będzie działo), wyjątku nie da się przegapić, przez co błąd robi się widoczny od razu w miejscu, gdzie powstał, a nie dwie metody dalej gdzieś w innej klasie. Podsumowując - zamiast bool daj void.
Nie rozumiem też nazewnictwa z podkreślinikiem jako prefiks (_connection). Daj tam normalną nazwę, a nie połamańca rodem z C. Zauważyłeś, że nie utworzyłeś obiektu SqlConnection i przy wywołaniu którejkolwiek z metod poleci wyjątek?

0
ŁF napisał(a):

Zauważyłeś, że nie utworzyłeś obiektu SqlConnection i przy wywołaniu którejkolwiek z metod poleci wyjątek?

 public void Initialize()
        {
            SqlConnection sqlconnection = new SqlConnection();
            string connString = @"Server=XXX\SQLEXPRESS;Database=rcp;Integrated Security=SSPI";
            _connection.ConnectionString = connString;
        }

Czy dobrze próbuję obsłużyć wyjątek?

 public void Connect()
        {
            try
            {
                this._connection.Open();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
              
              
        }
0

Nie. Informacja o tym, że coś się nie udało pozostanie tajemnicą dla reszty kodu. Spróbujesz się połączyć, poleci wyjątek, Ty go zobaczysz, ale dalszy kod już nie i pojawi się próba wykonania zapytania do bazy na połączeniu, które nie zostało otwarte i poleci kolejny wyjątek, tym razem już nieobsłużony. To jest właśnie sytuacja, którą przedstawiłem w poprzednim poście, przeczytaj go jeszcze raz wolniej i ze zrozumieniem.
IMHO łapanie wyjątku i niepuszczanie go dalej powinno być zawsze poprzedzone solidnym zastanowieniem się.

0

Tak, mniej wiecej ma to wyglądać?

public class DataBase
    {
        private SqlConnection _connection;
 
        public void Initialize()
        {
            SqlConnection sqlconnection = new SqlConnection();
            string connString = @"Server=XXX\SQLEXPRESS;Database=rcp;Integrated Security=SSPI";
            _connection.ConnectionString = connString;
        }
        public void Connect()
        {
             try
             {
             this._connection.Open();
             }
             catch
             {
             throw;
             }             
        }
        // Jeżeli ta metoda zwróci `true` to insert wykonał się prawidłowo (tak samo update i delete)
        // W przypadku selecta zwracasz nie `bool` tylko wynik zapytania albo np. `null`
        //public bool Insert(/* data */);
 
        // Jeżeli ta metoda zwróci `true` to jesteś prawidłowo rozłączony;
        public void Disconnect()
        {
             try
             {
             this._connection.Close();             }
             catch
             {
             throw;
             } 
            
 
        }
    } 
0

Mam wrażenie, że nie rozumiesz o co mi chodziło, mam rację?

public void Connect()
{
    try
    {
        this._connection.Open();
    }
    catch
    {
        throw;
    }             
}

Powyższa konstrukcja jest bezsensowna, bo jest równoznaczna tej:

public void Connect()
{
    this._connection.Open();
}

Nabierze sensu dopiero wtedy, kiedy catch ubierzesz w swój kod

void LogException(Exception ex)
{
    Console.WriteLine(ex.ToString()); // albo zamiast niekumatemu użytkownikowi walić w twarz treścią wyjątku jakiś sensowny logger, np. NLog: logger.Fatal(ex);
}


public void Connect()
{
    try
    {
        this._connection.Open();
    }
    catch (Exception ex)
    {
        LogException(ex); // albo od razu wywołanie jakiegoś loggera, który siedzi sobie w statycznej właściwości klasy, np. NLog, ale to chyba za kilkanaście miesięcy
        throw;
    }             
}
0
public void Connect()
{
    try
    {
        this._connection.Open();
    }
    catch(Expection ex)
    {
        MessageBox.Show(ex.Message);
    }             
} 

public void Disconnect()
{
    try
    {
        this._connection.Close();
    }
    catch(Expection ex)
    {
        MessageBox.Show(ex.Message);
    }             
} 
0

Czas zająć się metodą Insert:

 public bool Insert(/* data *///)
{
    String query = "INSERT INTO dbo.SMS_PW (numer,data,rodzaj,obszar,kierunek) VALUES(@numer,@data,@rodzaj,@obszar,@kierunek)";

    SqlCommand command = new SqlCommand(query, db.Connection);
    command.Parameters.Add("@numer","abc");
    command.Parameters.Add("@data","abc");
    command.Parameters.Add("@rodzaj","abc");
    command.Parameters.Add("@obszar","abc");
    command.Parameters.Add("@kierunek","abc");

    command.ExecuteNonQuery();
}

Czy w dobry sposób chcę odwołać się do tabel w bazie danych, z którą się łączę? I czy

command.Parameters.Add 

jest dobrym sposobem na wrzucanie danych do tabel?
Zastanawia mnie jeszcze jak wrzucić konkretne części łańcucha w odpowiednie miejsca.

1
  • Zamiast /* data */ wstaw jako argument klasę, która reprezentuje obiekt, który chcesz wrzucić do tej tabelki. Najlepiej jak taka klasa będzie reprezentowała tabelkę z bazy danych jeden do jednego, w sensie będzie posiadała wszystkie pola, które posiada ekwiwalent w bazie.
  • Parametrami będą np: command.Parameters.Add("@numer", obj.number); etc..., zakładając, że obj to wspomniany obiekt z punktu wyżej;
  • Zwracaj return command.ExecuteNonQuery() > 0; - będziesz wtedy wiedział czy insert się powiódł;
  • Możesz to jeszcze zapiąć w try catch, żeby wiedzieć czy coś się czasami nie wywala przy tym dodawaniu.

...jest dobrym sposobem na wrzucanie danych do tabel?

Tak. Parametryzowanie zapytania to dobry sposób.

1

Ok, czy ta klasa ma zawierać tylko obiekty odpowiadające polom w tabeli SQL?

Napisałem Ci to już.

Czy w tej samej klasie muszą być już przypisane do tych obiektów co ma być umieszczone w tabeli?

Załóżmy, że pola obiektu takiej klasy nie są zainicjalizowane i robisz inserta. Czy zrobi się poprawnie? Czy wstawi do bazy dane, które oczekujesz żeby wstawił?

Przykład klasy Person:

public class Person {
	public string Name { get; set; }
	public string Surname { get; set; }
}

I obiekt takiej klasy będzie np. argumentem funkcji insert.

0
public class Table
{
    public string Numer { get; set; }
    public string Data { get; set; }
    public string Rodzaj { get; set; }
    public string Obszar { get; set; }
    public string Kierunek { get; set; }
}

public bool Insert(Table)
{
    String query = "INSERT INTO dbo.SMS_PW (numer,data,rodzaj,obszar,kierunek) VALUES(@numer,@data,@rodzaj,@obszar,@kierunek)";
 
    SqlCommand command = new SqlCommand(query, db.Connection);
    command.Parameters.Add("@numer", obj.Numer);
    command.Parameters.Add("@data", obj.Data);
    command.Parameters.Add("@rodzaj", obj.Rodzaj);
    command.Parameters.Add("@obszar", obj.Obszar);
    command.Parameters.Add("@kierunek", obj.Kierunek);
 
    command.ExecuteNonQuery() > 0;
} 
0
grzesiek51114 napisał(a):

Zwracaj return command.ExecuteNonQuery() > 0; - będziesz wtedy wiedział czy insert się powiódł;

Jeśli się nie uda, to poleci wyjątek.

grzesiek51114 napisał(a):

(...) zapiąć w try catch, żeby wiedzieć czy coś się czasami nie wywala przy tym dodawaniu

???
Niezłapany wyjątek przecież leci na twarz użytkownikowi. Za to jeśli go złapiesz i zignorujesz/źle oprogramujesz, to wtedy dopiero jest szansa na jego przegapienie.

Komunikacja z bazą za pomocą SQL jest prosta, ale - pomimo prostoty - niewygodna, a na dłuższą metę uciążliwa w utrzymaniu. Samo budowanie stringów z zapytaniami może prowadzić do zrobienia dziur umożliwiających atak typu sql injection, na szczęście używasz parametrów, które uniemożliwiają to.
Dużo lepszym rozwiązaniem jest użycie jakiegoś ORMa, np.: Entity Framework, NHibernate. Wymagają one na starcie sporo wiedzy, jednak potem utrzymanie kodu gadającego z bazą danych jest tysiąc razy łatwiejsze.

0

Żeby sprawdzić w ogóle jak to działa i jak wynik mi to daje, zrobiłem coś takiego:

public class ProcessingService
        {
            public void ProcessFile()
            {
                var lines = File.ReadAllLines(@"U:\Users\mbednarek\Desktop\Rej.txt");
                var builder = new StringBuilder();

                for (int i = 0; i < lines.Length; i++)
                {
                    var line = lines[i];
                    builder.AppendFormat(
                        "{0} {1} {2} {3} {4}",
                        line.Substring(0, 5),
                        line.Substring(5, 14),
                        line.Substring(19, 2),
                        line[line.Length - 2],
                        line[line.Length - 1]
                        );

                    lines[i] = builder.ToString();
                    builder.Clear();
                    File.WriteAllLines(@"U:\Users\XXX\Desktop\nowy123.txt", lines);
                var split = lines[i].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                
                
                File.WriteAllLines(@"U:\Users\XXX\Desktop\split.txt", split);
            }
            
        }
        } 

Wynik jaki dostaje to:

00001
20160317131457
02
1
0
 

Niestety dalej nie wiem, w jaki sposób się odwołać do konkretnej części. Nie ważne co wpisze między nawias kwadratowy i tak dostaje taki sam wynik.
Dla mnie w dalszym ciągu jest to czarna magia.

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