środa, czerwiec 29, 2011

Ku pamięci – Jak zaimportować XML do bazy danych

Bawię się ostatnio publicznymi danymi udostępnionymi z serwisu devPytania (info tutaj O pewnym sukcesie) i już zanim przystąpiłem do próby analizy tych danych pojawił się problem.

Dane zostały udostępnione w formacie XML, który oczywiście mimo wszystkich swoich zalet o przenoszalności i dowolnego jego wykorzystania jest średnio zrozumiały przez MS SQL, które to chciałem zaprząc do tejże analizy. Tak więc pierwszą trudnością było to, jak wczytać takie dane do tabel.

Na sieci można znaleźć sporo postów mówiących, jak rozwiązać ten problem ale większość mówi jak XML’a wczytać po prostu do jednej kolumny bez analizy zawartości i stworzenia tylu wierszy w tabeli, ile głównych node’ów mamy w XMLu.
W końcu po prawie godzinie zmarnowanej na próbowaniu tego czy innego rozwiązania udało się znaleźć działający sposób (OPENXML). Prawie idealny.

DECLARE @idoc int
DECLARE @doc varchar(max)
SET @doc ='<xml>'
--Create an internal representation of the XML document.
EXEC sp_xml_preparedocument @idoc OUTPUT, @doc
-- Execute a SELECT statement that uses the OPENXML rowset provider.
INSERT Posts SELECT    *
FROM   OPENXML (@idoc, '/Posts/row',1)
WITH (Id int, PostTypeId int, CreationDate datetime2(7), 
Score int, ViewCount, Body ntext, OwnerUserId int, DeletionDate datetime2(7))

Co tu robimy? Na podstawie zmiennej @doc tworzymy dokument XML a następnie za pomocą OPENXML wybieramy odpowiednie elementy. Parametrami tego polecenia są: dokument XML, XPATH do wzorca wiersza jaki będziemy importować oraz flaga mapowania. Ten ostatni parametr zasługuje na krótkie przyjrzenie się mu. Odpowiada on za ustawienie tego, w jaki sposób będą mapowane dane z XMLa na kolumny w bazie.

0 – domyślnie; takie samo jak 1
1 - dane odczytywane z atrybutów
2 – dane odczytywane z elementów
8 – dane nie będą kopiowane do pola @mp:xmltext, które jest wykorzystywane w celach parsowania

Wartości można łączyć logiczną alternatywą. Czyli wg dokumentacji dozwolone są zarówno wartości 1,2 jak i 3,9 oraz 10.


Po wykonaniu takiego zapytania wiersze z pliku znajdą się w tabeli w bazie danych.

A czemu to prawie idealne rozwiązanie? Z dwóch powodów. Po pierwsze zawartość XML’a trzeba wkleić i podstawić do zmiennej @doc. Nie dałem rady zmusić T-SQL’a do zaczytania pliku i podstawiania wartości do tej zmiennej.
Drugi problem to wielkość danych. varchar to w T-SQL 8000 bajtów, tak więc przy większych plikach (a takowym był plik pytań i odpowiedzi) dane należało podzielić na mniejsze paczki ręcznie. Zmiennej typu text nie da rady utworzyć oczywiście.

Ktoś wie jak można to zrobić lepiej/ładniej/szybciej i ominąć te dwa powody?

wtorek, czerwiec 28, 2011

mRemote–narzędzie do zarządzania połączeniami zdalnymi

W pracy często spotykamy się z koniecznością logowania się do wielu serwerów zlokalizowanych w różnych miejscach. A to jakiś sewer buildów w jednej lokacji, a to produkcyjny w drugiej. Do dziś w tym celu miałem odpowiednio skonfigurowane i zapisane skróty do zdalnych pulpitów, ale takie rozwiązanie nie było zbyt wygodne. Ciężko też zarządzać grupą kilkunastu skrótów.

Od dziś przerzuciłem się na narzędzie mRemote. Pozwala ono zebrać w jedno miejsce wszystkie nasze zdalne pulpity, połączenie VNC, SSH i inne (lista obsługiwanych protokołów na stronie). Dzięki niemu, będziemy mogli zdefiniować wszystkie nasze połączenia w jednym miejscu i z niego nimi zarządzać.

mRemote - praca

Aplikacja także umożliwia zrobienie screenshotu ze zdalnego pulpitu (normalnie trzeba się trochę nagimnastykować) a dość często z tego korzystam.

Oczywiście nic nie stoi na przeszkodzie, aby mieć otwarte na raz kilka połączeń i w wygodny sposób przełączać się miedzy nimi za pomocą tabów. Aktualnie siedzę sobie z otwartymi dwoma zdalnymi pulpitami, zakładką pokazującą mi konfigurację mojego NAS’a oraz rutera. Oczywiście narzędzie darmowe. Sweet :).

poniedziałek, czerwiec 27, 2011

SOS w VisualStudio

Kolejny wpis z kategorii ‘nieznanych’. Dziś będzie o okienku Immediate Window. Wszyscy wiemy (?), że można w nim wykonywać wszelkie polecenia, jakie można by napisać w kodzie czyli np. var builder = new System.Text.StringBuilder() i będziemy mogli na tej zmiennej działać.

Ale za pomocą tego okna można napisać także .load sos (było to także możliwe w VS 2008). Co to nam da?
W większości przypadków wyświetli nam komunikat taki jak poniżej.

enable_unmanaged

Aby załadować SOS musimy włączyć unmanaged debugging w ustawieniach projektu.

managed-debugging

A to już da nam więcej. Będziemy mieli dostęp do wszystkich poleceń SOS!
Wtedy będziemy mogli wyświetlić stertę naszej aplikacji. Wystarczy wykonać polecenie !dumpheap –stat i gotowe. Czyli tak naprawdę wyświetlić informacje o wszystkich obiektach w naszym programie.

dumpheap_thumb7

Potem już z górki. Możemy wyświetlić informacje o konkretnej klasie, czyli !dumpheap –mt <adres>.

dumpheap2

Schodząc jeszcze niżej konkretnego obiektu: !do 02a0cbbc.

do

Lista poleceń nie ogranicza się tylko do tych wymienionych wyżej i daje dostęp do wszystkich poleceń modułu. Możemy analizować obiekty, kod i stos, struktury runtime’u oraz kilkanaście poleceń diagnostycznych. Pełna lista na zrzucie poniżej lub pod tym linkiem na MSDN.

help

Nice. Miłego SOS’owania.

czwartek, czerwiec 23, 2011

Analiza dumpów w VisualStudio

Postanowiłem napisać kilka postów, które odkrywają “nieznane” funkcje Visual Studio. Dziś jeden z nich.
Czasem widzę, że największą furorę robią posty opisujące rzeczy (dla mnie) oczywiste. Okazuje się, jednak, że to co jest znane mnie, niekoniecznie jest wiedzą dość dobrze rozpowszechnioną. Zaczynamy zatem.

Analiza dumpów

Jeszcze do wersji 2008 ta funkcjonalność zarezerwowana była tylko dla świetnego narzędzia jakimi jest WinDbg. Jednakże od wersji 2010 VisualStudio potrafi odczytać i przeanalizować pliki *.dmp czyli zrzuty pamięci.

dump

Za pomocą polecenia Open możemy wczytać taki plik i wyświetlić jego zawartość. Co więcej VisualStudio w ładny sposób potrafi pokazać nam, gdzie nasz program znajdował się w momencie wykonania zrzutu pamięci. Wystarczy, po załadowaniu pliku dumpa, wybrać opcję 'Debug with managed’ (bądź native – w zależności od potrzeb) a następnie skorzystać z opcji Parallel Stacks. Dzięki temu naszym oczom ukaże się ładny stan aplikacji w momencie zrzutu.

stacks

Teraz już bez problemu będziemy mogli znaleźć wątki naszej aplikacji i zobaczyć, że tak na prawdę dwa z nich próbują wstawiać elementy do tego samego słownika powodując wyjątek.

threads

Wcześniej, aby osiągnąć te rezultaty trzeba było analizować zrzut pamięci w WinDbg, co dla niektórych stanowiło barierę przed tego typu analizami. Co prawda WinDbg wspiera nas poleceniami typu !analyze –v –hang ale mimo to niewiele osób to robiło w jakikolwiek sposób.

analyze

Dodatkowo po załadowaniu SOS (.loadby sos clr) a potem po !DumpStack –short możemy zauważyć, że wątki 32 oraz 34 siedzą w tej samej metodzie a mianowicie Dictionary.Insert wywołanej w tym samym miejscu.

dict_insert

No więc mamy to samo co udostępnia teraz VisualStudio. Miłego analizowania zrzutów.

niedziela, czerwiec 19, 2011

Debugger Canvas–deep(er) dive

Jakiś czas temu Tomek Wiśniewski na swoim blogu opisał (Debugger Canvas – nowe spojrzenie na ”odrobaczanie”) ciekawy dodatek do Visual Studio a mianowicie Debugger Canvas.

Ponieważ lubię wszelkie rzeczy związane z “ odrobaczaniem” postanowiłem się trochę przyjrzeć mu bliżej. W tym wpisie chciałbym pokazać trochę dodatkowych “smaczków”, które są udostępnione za pomocą Debugger Canvas.

dc

Tak więc co dodatkowego posiada Debugger Canvas prócz tego co opisał Tomek? Na każdym z “bąbli” (wolę to określenie od chmurek) w prawym górnym rogu widoczna jest mała niebieska ikonka (to samo można uzyskać za pomocą opcji Locals Bubble). Po jej przyciśnięciu mamy dostęp do locals’ów czyli zmiennych widocznych w bieżącej ramce.

locals

Ale to nie wszystko, klikając ikonę aparatu możemy zrobić “snapshot” bieżących wartości i w kolejnym przebiegu programu możemy je porównywać z aktualnymi.

locals_cmp

Dzięki temu w prosty sposób możemy zaobserwować jakie zmiany zachodzą w programie i dlaczego w poprzednim przebiegu nasz program zachował się inaczej niż obecnie.

W domyślnym (i jedynym :)) swoim widoku, Debugger Canvas, wyświetla ciało jednej metody bądź właściwości. Z jednej strony ogranicza nasze pole widzenia tylko do tego co aktualnie istotne (wykonywany kod) z drugiej strony czasem pojawia się potrzeba zobaczenia czegoś więcej. Możemy wtedy skorzystać z małej czarnej strzałki w nagłówku każdego z bąbli.

other_stuff

Z listy, która się rozwinie możemy otworzyć w dodatkowych “bąblach” pozostałe fragmenty kodu dostępne na danym obiekcie.

Możemy również podkreślić całą ścieżkę wykonania programu klikając na strzałki pomiędzy bąblami. Ścieżka wykonania będzie oznaczona się wtedy na czerwono.

path

Dodatkowo pod prawym przyciskiem myszy mamy możliwość utworzenia notatki, czy też wyszukania fragmentu kodu.

stickynoteFindCode

W opcjach jak na razie jest niewiele ustawień. Mamy możliwość włączenia edycji kodu w “bąblach”, ale w chwili obecnej jest to opcja eksperymentalna i może spowodować, iż nasze Visual Studio przestanie działać.

options

Na koniec cały efekt naszej pracy, o czym wspominał Tomek, możemy zapisać do XPS’a i podesłać koledze aby zapoznał się z naszymi obserwacjami.

Podsumowując - Debug Canvas to interesujący dodatek. Przedstawienie kodu w postaci grafu przejścia może pomóc w łatwiejszym zrozumieniu co dzieje się z naszym programem i szybszym wyśledzeniu błędu.

poniedziałek, czerwiec 13, 2011

VirtualStudy – Moje sesje

Poniżej linki do moich sesji na portalu VirtualStudy z cyklu kurs C#. Przeznaczone główne dla osób początkujących, choć z sesji o reflection i atrybutach być może i ktoś z większą wiedzą także skorzysta :).
16. Czym są wyrażenia regularne - prezentacja, przykłady.
18. Odczyt danych z i do pliku - prezentacja, przykłady.
19. Poznajmy atrybuty i mechanizm refleksji - prezentacja, przykłady
20. Dostęp do danych to podstawowa funkcjonalność programów, zobaczmy, jak to się robi - prezentacja, przykłady
24. Wzorce projektowe - prezentacja, przykłady
Oczywiście dla zainteresowanych polecam pozostałe filmy z kursu C# jak też inne sesje z portalu VirtualStudy.pl

sobota, czerwiec 04, 2011

3 problematyczne zagadnienia dla początkującego dotnetomaniaka

Ostatnio, przez ponad pół roku, wraz z Wojtkiem Poniatowskim, Mirkiem Pragłowskim, Tomkiem Wiśniewskim prowadziliśmy kurs C# na portalu VirtualStudy. Kurs przeznaczony był dla osób początkujących ale dzięki temu miałem możliwość zobaczenia jakie elementy .NET i C# sprawiają najwięcej trudności osobom, które dopiero zaczynają swoją przygodę z tą technologią. Jeśli masz choć trochę doświadczenia z .NET to zapewne nie znajdziesz tu zbyt wielu przydatnych informacji. Tak czy inaczej zapraszam do czytania:

jawny typ vs. var vs dynamic

Po ilości pytań odnośnie tego zagadnienia wnioskuję, że jest to numer jeden “problemów” z jakim muszą sobie poradzić osoby dopiero zaczynające w .NET. Podawać typ? Użyć var? A tak w ogóle czym to się różni od tego dynamic? Zacznijmy zatem od początku. Dawno dawno temu w czasach .NET 2.0 i wcześniejszych aby zadeklarować i utworzyć zmienną należało posłużyć się następującą konstrukcją

Importer importer = new Importer();

Czyli nazwa typu, potem nazwa zmiennej i przypisanie wartości. Widać, że jest to dość spora duplikacja. Skoro po prawej stronie po słowie kluczowym new mamy już nazwę typu po co podawać ją jeszcze z lewej strony? Wychodząc z tego założenia twórcy .NET w jego wersji 3.5 dołożyli słowo kluczowe var. Dzięki temu od frameworka w tej wersji możemy napisać

var importer = new Importer();

i ma to takie samo znaczenie jak powyższy zapis. Słowo kluczowe var mówi kompilatorowi – jestem zbyt leniwy, aby podać jawnie typ, ale ty drogi kompilatorze domyśl się jaki powinien on być i wpisz go za mnie zanim przeprowadzisz kompilację. Dzięki temu nasz program jest nadal silnie typowany.

Niestety dzięki temu można tworzyć kod, który czyta się dość ciężko a mianowicie taki:

var user = GetLoggedUser();

Czemu jest on taki zły? Dlatego, że bez sprawdzenia w nagłówku metody GetLoggerUser, lub bez najechania kursorem myszy na słówko var nie zobaczymy, jakiego typu jest user. Skoro var ma takie minusy czemu został w ogóle wprowadzony do języka? Bez niego ciężko byłoby działać z użyciem LINQu. W prostych przypadkach moglibyśmy typ podawać jawnie, ale pewnie niewielu osobom będzie się chciało domyślać się jaki będzie typ wyrażenia

Enumerable.Range(0, 1000).Where(i => i%5 == 0 || i%3 == 0).GroupBy(x => x%3)

Dzięki var, możemy to wyrażenie przypisać do zmiennej, którą zadeklarujemy z tym słowem kluczowym i kompilator sam domyśli się typu. My nie tracimy czasu na określanie typu (który byłby dość długi) a nadal mamy pełne silne typowanie.

Drugim przypadkiem, także w LINQu, są typy anonimowe. Bez var, nie moglibyśmy napisać

var anonimowy = new {Title = "Anonimowi", Age = 99};

Skoro wiemy już jaka jest różnica pomiędzy jawnym podaniem typu a var to czymże jest dynamic? To słowo kluczowe jest nowością w .NET 4 i oznacza, że nie wiemy jaki jest typ zmiennej. Nie wiemy jakie udostępnia ona metody i właściwości. Dopiero w runtime może się okazać czy dana metoda istnieje na tym obiekcie czy nie. Dzięki dynamic możemy wywołać dowolną metodę i kompilator zbuduje nasz program bez przeszkód. Dopiero jednak w runtime okaże się czy dana operacja powiedzie się i czy podana metoda istnieje na obiekcie. Zobaczmy na przykładzie, czym różni się dynamic od var i jawnego typu.

Zdefiniujmy sobie 3 zmienne

string zmienna = "jawny typ";

var zmiennaVar = "var";

dynamic zmiennaDynamic = "dynamic";

Zobaczmy na co pozwoli nam kompilator. W przypadku zmienna oraz zmiennaVar mamy dostęp tylko i wyłącznie do metod zdefiniowanych na typie string (+ wszystkie extension metody). Jeśli chodzi o zmiennaDynamic

zmiennaDynamic.EndsWith("dynamic");

zmiennaDynamic.JakasFajnaMetodaNieistniejąca();

Możemy podać cokolwiek. To czy zadziała dowiemy się dopiero podczas uruchomienia. Po cóż takiego? Pomaga to w przypadku używania np. obiektów zdefiniowanych za pomocą komponentów COM.

using vs using(IDisposable)

Kolejna rzecz, która na początku wprawia w lekkie zakłopotanie szczególnie, gdy ktoś mówi, iż dane wywołanie należy umieścić w klauzuli using. Od razu pojawiają się pytania, zaraz zaraz czy using nie stosujemy aby dodać przestrzeń nazw do naszej aplikacji? Używamy, jednak using ma jeszcze drugie użycie, które wiąże się z typem IDisposable. Pomińmy zatem using w kontekście dodawania przestrzeni nazw.

using (FileStream stream = new FileStream("plik.txt",FileMode.Open))

{

 

}

Taka konstrukcja jest równoważna następującej.

FileStream stream = null;

try

{

    stream = new FileStream("plik.txt", FileMode.Open);

    //...

}

finally

{

    if (stream != null)

        stream.Close();

}

Widzimy, że w rozwiniętej formie przypisanie do zmiennej następuje w bloku try, a zamknięcie otwartego pliku w bloku finally. natomiast pierwsza forma jest dużo wygodniejsza i bardziej czytelna. Czy musimy tak robić z typami IDisposable? Prosta odpowiedź – nie. Bardziej złożona – nie, ale…ale musimy pamiętać, że możemy mieć wycieki pamięci. Ale jak to? Przecież w .NET jest GarbageCollector, który zwalnia za nas pamięć. Mając w pamięci to zdanie przechodzimy do ostatniego tematu.

Wycieki pamięci w .NET

Tak, tak. Mimo, że w .NET mamy GC, który dba o zwalnianie pamięci to wycieki są możliwe. Jak? GC dba tylko o zwalnianie zasobów zarządzanych (managed, choć też nie zawsze – o tym może kiedy indziej). Z tymi unmanaged sobie nie poradzi, gdyż nie będzie wiedział kiedy mogą być one zwolnione. Jakie to są zasoby unmanaged? Pliki, połączenia do bazy danych, pędzle (Brush) itp.. I po to jest zaimplementowany interface IDisposable, abyśmy mogli w przystępny sposób, za pomocą wywołania Dispose powiedzieć GC kiedy już danego zasobu nie potrzebujemy i kiedy go można zwolnić.
Trzeba uważać na ten interface, gdyż wiele początkujących osób łapie się na tym, że gdzieś kiedyś usłyszało, że w .NET wycieków pamięci być nie może i tkwią w takim przeświadczeniu dość długo.

Tyle jeśli chodzi o zauważone przeze mnie pytania od osób, które (z reguły) zaczynają przygodę z .NET. A jakie były wasze spostrzeżenia gdy zaczynaliście przygodę z .NET?

Jakby ktoś chciał obejrzeć filmy z sesji z kursu C# to są one dostępne na stronie Spis publikacji.