ADO.NET SqlDataAdapter cz.3 – Primary key

 

W poprzedniej odsłonie pokazałem jak skorzystać z właściwości SqlDataAdapter do pobrania danych z bazy oraz ich wstawienia. Może się zdarzyć jednak tak, że przed dokonaniem aktualizacji danych w bazie chcemy wykonać na nich pewne operacje, jak np. wstawienie wielu wierszy. Jednocześnie miło byłoby zachować kontrolę nad wstawianymi danymi z poziomu aplikacji. Jedną z informacji przydatnych przy tej operacji z pewnością będzie znajomość klucza głównego. W przypadku stworzonej przeze mnie tabeli na potrzeby prezentacji zagadnienia co prawda kolumna ta, zawierająca identyfikator adresu (wartość int) jest automatycznie inkrementowana, ale warto wiedzieć jak poradzić sobie z tą sytuacją jeśli kolumna z kluczem głównym nie posiada takiego atrybutu. Ponadto pokażę jeszcze inną zaletę jaka wynika ze znajomości klucza głównego. Zatem do dzieła.

Przede wszystkim, warto zacząć od tego, że wypełniając zbiór danych DataSet za pomocą metody Fill(), obiekt typu SqlDataAdapter nie przekazuje temu zbiorowi danych prawie żadnych informacji o tabeli, z której pobierane są dane. Z tego punktu widzenia interesujące jest wykonanie takiego kodu:

...

//As before "da" is SqlDataAdapter object
//and "ds" is DataSet object
da.Fill(ds);
da.Fill(ds);
...

Jego wykonanie, np. poprzez dwukrotne naciśnięcie przycisku pobierania danych (jeśli obiekt DataSet jest przechowywany w pamięci), spowoduje pobranie danych z bazy, a następnie ponowne pobranie, które skutkuje dopisaniem na końcu zbioru tych samych danych. Dla przypomnienia w tabeli Addresses założone zostało ograniczenie unikalności, jak zatem łatwo wywnioskować próba zapisania tych samych danych w bazie zakończy się wyrzuceniem wyjątku SqlException. Z pomocą w takiej sytuacji przychodzi właśnie klucz główny. Informacja o tym, że tabela w zbiorze DataSet posiada informację o tym, w której kolumnie znajduje się klucz główny spowoduje, że podczas ponownego pobrania danych obiekt typu SqlDataAdapter dokona jego sprawdzenia i tym samym uniemożliwi ponowne wpisanie powtarzających się danych.

Jedną z metod pozwalającą na pobranie informacji o kluczu głównym jest właściwość MissingSchemaAction dla SqlDataAdapter-a. Jest ona typu wyliczeniowego, przy czym szczególnie interesująca jest wartość AddWithKey:

da.MissingSchemaAction = MissingSchemaAction.AddWithKey;

Dodanie takiej linii do kodu uniemożliwi powtórne pobranie istniejących już danych w DataSet. Ponadto pobierane są w ten sposób jeszcze dwa inne atrybuty: MaxLength oraz AllowDBNull. Co do tego punktu mam jednak dwie uwagi. Po pierwsze w książce “Programming Microsoft ADO.NET 2.0 Core Reference” widnieje adnotacja, że jeśli tabela DataTable w naszym zbiorze jeszcze nie istnieje albo nie zawiera żadnych kolumna to wtedy SqlDataAdapter odpytuje bazę danych o informację o kluczu głównym. Z moich obserwacji wynika jednak, że równie dobrze można wykonać powyższy kod już po wstawieniu danych a przed ponownym pobraniem i informacja o kluczu głównym również zostanie wtedy pobrana i odpowiednio zastosowana. Druga uwaga odnosi się do atrybutu AllowDBNull. W moim zastosowaniu dane wstawiane są do DataSet z poziomu formularza wypełnianego przez użytkownika.
 
row["Street"] = StreetTextBox.Text;

Inaczej jednak niż ja bym tego oczekiwał to, że w polu tekstowym nie znajdują się żadne dane nie oznacza, że posiada ono wartość null. Podane ograniczenie zadziała dopiero w momencie jawnej próby wpisania do odpowiedniego pola w wierszu tabeli wartości null. Po wykonaniu stosownego kodu otrzymujemy wówczas informację:
 
A first chance exception of type ‚System.Data.NoNullAllowedException’ occurred in System.Data.dll

Column ‚Street’ does not allow nulls.
 
Naturalnie można również sprawdzić, że po wykorzystaniu właściwości MissingSchemaAction z wartością AddWithKey nie można wpisać w kolumnie z kluczem głównym powtarzającej się wartości:
 
A first chance exception of type ‚System.Data.ConstraintException’ occurred in System.Data.dll

Column ‚Addr_Id’ is constrained to be unique.  Value ’17’ is already present.
 
Warto jednak zauważyć, że nawet dla domyślnej wartości, czyli Add, atrybut autoincrement dla kolumny dla nowo wstawianych danych jest przestrzegany.

Drugą metodą na pobranie informacji o kluczu głównym jest wykorzystanie metody FillSchema():

//Gets only schema
da.FillSchema(ds, SchemaType.Source);

//Gets data from database
ds.Fill(ds);

Jako drugi parametr przekazywana jest informacja czy mają być zastosowane ustawienia dla kolekcji TableMappings, co nie było jeszcze przeze mnie omawiane, zatem przyjmijmy, że musi być on ustawiony na SchemaType.Source. Metoda ta również ustawia właściwości (atrybuty) AutoIncrement, AllowDBNull oraz MaxLength na zbiorze do którego zwracane są wyniki, a ponadto pobiera informację o kluczu głównym. Samo wywołanie metody FillSchema() nie powoduje pobrania danych, a jedynie informacji o schemacie. Z tego powodu dane należy pobrać osobnym poleceniem, jak pokazane zostało to w przykładzie.
Reklamy

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s

%d blogerów lubi to: