DataAdapter - jak zmienić coś w bazie danych?


(Przemek89k) #1

Mam pytanie,

wiem jak połączyć się z bazą danych, jak pobrać coś z niej i załadować przy pomocy DataAdaptera do Dataset.

Dataset pozwala pracować niezależnie od źródła danych - więc załóżmy, że zmienię sobie tam kilka rekordów i teraz chciałbym je zaktualizować jak to zrobić ?

Odnośnie pobierania z bazy mam taką metodę :

public bool pobierz(string pytanie,ref Databazy zapisz, MySqlConnection polaczenie) {

            try

            {

                MySqlDataAdapter adapter = new MySqlDataAdapter();

                adapter.SelectCommand = new MySqlCommand(pytanie, polaczenie);

                adapter.Fill(zapisz);

                return true;

            }

            catch {


                return false;

            }

        }

Jak z powrotem wysłać do bazy zaktualizowany dataset.... - czy się tak w ogóle da ?

I jeszcze jedno pytanie - jeżeli w bazie danych mam 15 rekordów, a ja za pomocą w/w polecenia select pobiorę do dataset tylko 5 (za pomocą "where") i powiedzmy 3 z nich zmienię, to jeżeli spowrotem wyślę dataset do bazy danych (całego) to w bazie danych nadal pozostanie 15 rekordów (żeby nie pomyślał, że bazę "skroiłem" wyłącznie do tych 5) ....

-- Dodane 07.12.2011 (Śr) 21:33 --

Głównie chodzi mi o to, skąd teraz dataadapter ma wiedzieć, jaką bazę ma zaktualizować przy pomocy Dataset - bo jeżeli zrobię :

MySqlDataAdapter adapter = new MySqlDataAdapter();

adapter.update(zapisz);

gdzie zapisz to mój dataset - to nie będzie wiedział gdzie to zaktualizować, te wszystkie rekordy na raz - czy trzeba je pojedyńczo ?


(Tomek Matz) #2

Przejrzyj sobie ten temat: http://forum.dobreprogramy.pl/aktualizacja-bazy-access-t454920.html. Tyczy się wprawdzie innej bazy danych, ale to nie ma żadnego znaczenia, bo mechanizmy są podobne. BTW "czyste" ADO .NET to nie jest jedyna technologia dostępu do danych w .NET :slight_smile:

Jeśli chodzi o to skąd DataAdapter wie co ma zrobić z danym wierszem: http://msdn.microsoft.com/en-us/library/system.data.datarow.rowstate.aspx.


(Przemek89k) #3

Dzięki,

ale mam jeszcze wątpliwość - tworzę ręcznie dataadaptery oraz Dataset (też ręcznie modeluję) - dataadaptery są osobno (nie ma ich w datasecie) i teraz skąd taki dataadapter :

MySqlDataAdapter adapter = new MySqlDataAdapter();

ma wiedzieć o jaki connection string chodzi ?

Czy może muszę pamiętać tego dataadaptera, który zrobił Fill i na nim bazować - bo on ma connection stringa (patrz 1 post) ?

-- Dodane 08.12.2011 (Cz) 14:33 --

PS: Czy to może działa w ten sposób :

polaczenie - to moj connectionstring (OledbConnection)

adapter.UpdateCommand.Connection = polaczenie;

I teraz adapter wie, ze jak bedzie update to ma to zrobic na bazie danych zlokalizowanej w Connectionstringu ?

Czyli robiąc adapter.update(tabela_dataset); - zapisze zmiany w bazie danych zlokalizowanej po moim connection stringu ?

-- Dodane 08.12.2011 (Cz) 14:37 --

I jeszcze jedno - czy mogę zrobić Update całego Dataset - czy muszę podawać tam tylko konkretne rekordy ?

tzn. adapter.update(tabela_dataset) - to przejdzie, ale czy będzie ok także adapter.update(dataset); ??

Chciałbym aby użytkownik po kliknięciu przycisku dokonał aktualizacji bazy - a nie za każdym razem jak dokona jakiś zmian ... czyli np. zmodyfikuje 5 rekordów (zmienię je w datasecie (acceptchange)) i chciałbym aby po kliknięciu przycisku te 5 rekordów powędrowało do bazy danych bez robienia pętli i wstawiania do adaptera każdego rekordu osobno.


(Tomek Matz) #4
  1. Każdy Command (Select, Update, Delete, Insert), który ustawiasz w DataAdapter, ma przypisany obiekt Connection. Stąd właśnie DataAdapter wie z jaką bazą danych ma się połączyć. W związku z tym nie musisz przechowywać referencji do DataAdapter, który wywołał metodę Fill.

  2. Wydaje mi się, że nie możesz zrobić Update całego DataSet. DataAdapter przygotowywany jest dla konkretnej tabeli (łatwo to sprawdzić, wystarczy spojrzeć na polecenia Insert, Update, Delete). Choć muszę przyznać w dokumentacji widnieje przeciążona metoda Update przyjmująca jako parametr tylko i wyłącznie DataSet http://msdn.microsoft.com/en-us/library/at8a576f.aspx. Możesz się jej przyjrzeć.

  3. W linku, który podałem (w poprzednim poście), jest przykładowy kod, możesz go sobie przejrzeć. Jest tam pokazane m.in. jak używać transakcji w połączeniu z obiektem DataAdapter.


(Przemek89k) #5
1. Każdy Command (Select, Update, Delete, Insert), który ustawiasz w DataAdapter, ma przypisany obiekt Connection. Stąd właśnie DataAdapter wie z jaką bazą danych ma się połączyć. W związku z tym nie musisz przechowywać referencji do DataAdapter, który wywołał metodę Fill.

Ale jak to możliwe .... ? Skoro tworzę nowy DataAdapter w code-behind (nie za pomocą kreatora Dataset) :

MySqlDataAdapter adapter = new MySqlDataAdapter();

To jeżeli następne polecenie będzie update -> adapter.update(tabela); - to jakim cudem, ma on wiedzieć do jakiej bazy ma się połączyć - przecież nigdzie mu nie przekazałem connection stringa......

-- Dodane 09.12.2011 (Pt) 11:27 --

PS: Co do polecenia command to rozumiem tzn :

Jeżeli zrobię adapter.SelectCommand = new MySqlCommand(pytanie, polaczenie); - to wtedy przekazuję zarówno polecenie, oraz connection stringa (polaczenie).

Ale, ja chciałbym dokonać aktualizacji bazy za pomocą zmodyfikowanej tabeli dataset - czyli w tym przypadku do konstruktora przekazuję 1 paramter :

adapter.Update(DataRow);

żadnego Connection Stringa tutaj nie mam - czyli wychodzi na to, że muszę pamiętać referencję do dataadaptera, który zrobił Select ...?

Chyba że dla rozwiązania powyżej mogę zrobić adapter.UpdateCommand.Connection = polaczenie;

i skorzystać z samego adapter.Update(DataRow); - i wtedy będzie miał connection stringa ...?


(Tomek Matz) #6

Tworzysz sobie jakiś DataAdapter tak jak pokazałeś, czylli MySqlDataAdapter adapter = new MySqlDataAdapter(); i zaraz potem wywołujesz metodę Update(). W porządku ... powiedz mi tylko skąd ten adapter ma wiedzieć jakie polecenie SQL ma wykonać? Przecież nie poinformowałeś go o tym. Nie ustawiłeś właściwości UpdateCommand.

Jeśli przejrzałeś kod, do którego powyżej dałem link, to zapewne widziałeś, że ja tam porobiłem sobie klasy dla różnych adapterów (przez różne rozumiem operujące na różnych tabelach). W obrębie każdej z tych klas zdefiniowałem polecenia Update itd. Tak więc tworząc obiekt takiej klasy nie muszę przejmować się tym, żeby ustawić właściwości UpdateCommand itd., bo wiem, że to wszystko już zostało za mnie zrobione w momencie tworzenia obiektu.


(somekind) #7

desperado , dlaczego tak bardzo chcesz użyć DataSetów i DataAdapterów? Nie są to zbyt elastyczne i wygodne rozwiązania. Nie myślałeś o użyciu czegoś innego?


(Przemek89k) #8

Ale przecież mogę wykonać polecenie adapter.update(tabela); - dzięki temu będzie wiedział, że ma zaktualizować dany rekord, i dlatego nie wykonuję adapter.selectcommand()...

Czegoś innego tzn. ?


(Tomek Matz) #9

@desperado

Kompletnie nie rozumiem o czym teraz mówisz.


(somekind) #10

Jakiegoś ORMa, nawet Entity Framework.