Kiedy nie warto używać DataSet Designera

Każdy kto oglądał chociaż jedną prezentację na temat Visual Studio, wie jak efektowny jest DataSet Designer dołączony do tego narzędzia. Pozwala on na szybkie zmapowanie struktur bazy do struktur w kodzie przez co otrzymujemy silnie typowanego DataSeta. Dzięki temu można odwoływać się do elementów DataSeta “po kropce”, czyli np. DataSet.Tabela1.Wiersze[5].KolumnaA.

Jest to dosyć wygodne narzędzie i na początku wydaje się, że dzięki niemu będzie można podbić świat i okoliczne galaktyki. Jednak rzeczywistość wygląda tak, że to narzędzie może służyć do podbicia podwórka ew. osiedla albo miasta, ale już kraju to się tym nie podbije.

Kreator DataSeta jest przydatny jeżeli masz do napisania prostą aplikację. Powiedzmy 3-4 tabele i mało relacji, mało obliczeń. Przydatny jest także do programów dla nauki. Wtedy możesz szybko przygotować widoki na dane, ekrany edycyjne, szybko zrobić obliczenia statystyczne. Jednak jeżeli piszesz komercyjny program, który ma działać dobrze i chcesz zapewnić sobie spokój w nocy, po prostu zrezygnuj z kreatora DataSeta.

Oczywiście ten post nie ma na celu zniechęcać całkowicie do kreatora, ale dać szerszy obraz tego, jakie przygody czekają na podróżnika, który odwiedzi świat kreatora DataSeta.

Problemy przedstawione w tym poście dotyczą zarówno wersji Visual Studio 2005 jak i VS 2008, w której to nie zmieniło się dużo jeżeli chodzi o architekturę kodu generowanego przez kreator. A zaczniemy od niego. Cała zabawa w pisanie dobrego kreatora polega na tym, żeby kod przez niego wygenerowany był łatwo debuggowalny jeżeli coś pójdzie nie tak. W końcu błędów w zaprojektowaniu kreatora nie da się uniknąć. Chcemy mieć pewność, że jeżeli kreator zadziała nie tak, będziemy mogli ręcznie naprawić jego błędy.

Czytaj podobne  10 fiszek dla osób uczących się JavaScriptu

Skąd błędy w kreatorze DataSeta

Tak jest w przypadku kreatora okien (designera okien), ale nie w przypadku kreatora DataSeta.  Kod generowany jest w sposób chaotyczny, a elementy, które powinny być ze sobą jasno powiązane, nie są. Spójrz na ten kawałek wygenerowanego kodu:

[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
private void InitCommandCollection() {
this._commandCollection = new global::System.Data.SqlClient.SqlCommand[2];
this._commandCollection[0] = new global::System.Data.SqlClient.SqlCommand();
this._commandCollection[0].Connection = this.Connection;
this._commandCollection[0].CommandText = “SELECT ID, NAME from tabTabela”;
this._commandCollection[0].CommandType = global::System.Data.CommandType.Text;
this._commandCollection[1] = new global::System.Data.SqlClient.SqlCommand();
this._commandCollection[1].Connection = this.Connection;
this._commandCollection[1].CommandText = “SELECT ID, TELEFON from tabUser”;
this._commandCollection[1].CommandType = global::System.Data.CommandType.Text;
}

[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.ComponentModel.Design.HelpKeywordAttribute(“vs.data.TableAdapter”)]
[global::System.ComponentModel.DataObjectMethodAttribute(global::System.ComponentModel.DataObjectMethodType.Fill, true)]
public virtual int Fill(MyDataSet.MyDataTable dataTable) {
this.Adapter.SelectCommand = this.CommandCollection[0];
if ((this.ClearBeforeFill == true)) {
dataTable.Clear();
}
int returnValue = this.Adapter.Fill(dataTable);
return returnValue;
}
Co z tego przydługiego kodu wynika? Otóż to, że w kodzie wygenerowanym przez kreatora SqlCommand nie jest powiązane z metodami. Po prostu ktoś kto pisał tego kreatora, przyjął, że zapytania do bazy danych będą trzymane w  kolekcji _commandCollection, a w momencie wywołania konkretnej metody, odpowiednie zapytanie zostanie wstawione do SqlDataAdapter tego kreatora (czyli this.Adapter). W ten sposób nie można określić z jakiego zapytania korzysta na przykład metoda Fill, albo inna, własna, którą możesz przecież dodać z poziomu kreatora. Czyli reasumując: widzisz zapytanie w kreatorze, ale z poziomu kodu nie wiesz jakie zapytanie (PobierzUnikalneImiona, PobierzSumeVat itp.) korzysta z jakiego zapytania (‘Select distinct First_Name’, “Select SUM(VAT)’).

Zazwyczaj wiedza ta nie jest potrzebna. Jednak sposób zaprojektowania tego rozwiązania jest przykładem wielu miejsc w kodzie generowanym przez kreatora gdzie trzeba wróżyć z fusów. Jest to o tyle ważne, że obsługa tego kodu działa w dwie strony: na podstawie tego co ustawiasz w kreatorze jest tworzony kod DataSeta, a z kodu DataSeta jest tworzone to co widzisz w kreatorze. A w tym miejscu twórca kreatora musi domyślać się jakie zapytanie jest powiązane z jaką metodą. Domyślanie się takich rzeczy jest niebezpieczne, bo może prowadzić do błędów i tak się właśnie dzieje czasem w kreatorze. Takie miejsca powodują, że czasem typowany DataSet po prostu się psuje. Dlatego proste poprawianie bugów w kodzie DataSeta tutaj nie wystarczy, trzeba by było zmienić sposób w jaki kreator serializuje ustawienia do kodu. Wtedy szanse na błędy podczas tego zamkniętego cyklu kod-kreator byłyby mniejsze.

Czytaj podobne  Ewolucja języka

Problem jest taki, że każdy taki błąd zniechęca użytkowników do używania kreatora i tak jest też w tym przypadku. Coś podobnego można było zaobserwować gdy rozwijał się rynek programów WYSIWYG do tworzenia stron internetowych. Po latach uciążliwości z FrontPage, który generował wielkie, nieoptymalne, nieczytelne i często wadliwe pliki HTML (wtedy jescze), pojawił się konkurencyjny program Dreamweaver, który generował piękny kod HTML. W miejscu gdzie była spacja była spacja a nie dziesiątki niepotrzebnych znaczników z których każdy zwiększał ryzyko tego, że strona nie będzie chodzić poprawnie nigdzie poza FrontPage. Dreamweaver pokazał, że można generować i interpretować przejrzysty kod i że to jest droga do osiągnięcia sukcesu z kreatorami. Szkoda, że w tym przypadku team Visual Studio nie uczy się z innych obszarów działalności swojej firmy.

O tym problemie pisałem już przeszło 2 miesiące temu na Connect i bez odzewu. Możliwe, że już wystarczająco dużo osób zniechęciło się do tego designera, żeby team VS planował go dalej rozwijać.

Jak zapobiec błędom

Tutaj pojawia się problem. Ponieważ jeżeli kreator DataSeta popełni błąd tak że nie będzie się uruchamiał znowu to jedyne co zostaje to otworzyć ręcznie kod i znaleźć błąd i go usunąć. Niestety w tym momencie twórcy DataSeta typowanego nie dają żadnej pomocy. Zakładają przy tym pewnie, że wygenerowany kod będzie działający w 100%. Niestety tak nie jest i czasem dzieje się tak, że za którymś razem kreator po prostu już się nie otworzy. Na przykład przez taki błąd:

Column requires a valid DataType.

Oprócz informacji o tym, że któraś kolumna nie ma poprawnego typu nic więcej się nie dowiemy. Podpięcie drugiego Visuala tutaj nic nie da. Tak samo Stack Trace, który wcale nie zaskakująco wygląda tak:

at System.Data.DataColumn.set_DataType(Type value)
at System.Data.XSDSchema.SetProperties(Object instance, XmlAttribute[] attrs)
at System.Data.XSDSchema.HandleElementColumn(XmlSchemaElement elem, DataTable table, Boolean isBase)
at System.Data.XSDSchema.HandleParticle(XmlSchemaParticle pt, DataTable table, ArrayList tableChildren, Boolean isBase)
at System.Data.XSDSchema.HandleComplexType(XmlSchemaComplexType ct, DataTable table, ArrayList tableChildren, Boolean isNillable)
at System.Data.XSDSchema.InstantiateTable(XmlSchemaElement node, XmlSchemaComplexType typeNode, Boolean isRef)

(dalsza część pominięta dla przejrzystości postu)

Nie pozostaje w tym momencie nic jak szukanie na oślep w kodzie wygenerowanym przez kreator. A wystarczyłoby dodać odpowiednią informację jakiej kolumny dotyczy błąd. Wtedy znalezienie problemu na własną rękę byłoby możliwe. No bo nie oszukujmy się, że przy zastosowanej architekturze kodu ręczne naprawy są nieuniknione.

Podsumowanie

Podsumowując staraj się używać kreatora DataSeta z głową i nie zawsze. Jest to wygodne narzędzie – owszem. Ale tylko do pewnego momentu. Zwłaszcza nie polecam korzystania z DataSeta bez robienia kopii zapasowych albo posiadania kontroli wersji. A jaka będzie przyszłość tego narzędzia? Czy będzie poprawiane? Nie sądzę i raczej myślę, że w końcu zostanie wprowadzony zamiennik, który będzie to wszystko realizwał zupełnie inaczej, bo na podstawie tego co jest nie da się dużo naprawić w zachowaniach kreatora DataSeta. Pozostaje mieć nadzieję, że team VS uczy się na błędach i nie popełni tych samych w przypadku kolejnych kreatorów, które są nieuniknione w środowiskach RAD.

Przeczytaj też

Najlepsza książka do Pythona Nie wiesz, z jakiej książki/ebooka uczyć się programowania w języku Python? Postanowiłem zrobić zestawienie 10 książek z Heliona na ten temat, abyś mó...
Komplet 28 ebooków i kursów, aby zostać programist... Od jakiegoś czasu dostaję zapytania na temat tego jakie książki, kursy i ebooki polecam. W związku z tym postanowiłem przygotować dzisiaj zestaw, któr...
120 tapet programistycznych za darmo do pobrania Trochę mi się nudziło, więc przygotowałem zestaw 120 tapet dla programistów. Możesz go pobrać. Tapety są w rozdzielczości 1366x768. Podzielone ...
10 fiszek do nauki programowania w Pythonie Uczysz się programowania w Pythonie? Pobierz te 10 fiszek, które ułatwią Ci zapamiętanie funkcji wbudowanych* w Pythona! Programowanie potrafi ...
Napisano w Kolumna Tagi: , , , , , , , , , , , , , , , , , , , , , , , ,

Menu