wtorek, 15 kwietnia 2014

Asynchroniczne pobieranie danych i uaktualnianie CollectionView w WPF

W WPF klasa CollectionView jest niezwykle przydatna jeśli chcemy w prosty sposób zaimplementować mechanizm sortowania, grupowania lub filtrowania. Używając jej jednak w programowaniu asynchronicznym podczas uaktualniania tej kolekcji z innego wątku, dostaniemy następujący komunikat:

The calling thread cannot access this object because a different thread owns it

Nie dziwota, jest to normalnie zachowanie, które często się zdarza, ponieważ CollectionView nie obsługuje zmian własnej kolekcji z wątku innego niż Dispatcher. Co jednak zrobić aby obejść ten problem? Po pierwsze musimy mieć obiekt dispatcher'a, która w WPF'ie jest klasą zapewniającą usługi do zarządzania wątkami, np. synchronizacji. Jeśli korzystamy ze wzorca MVVM (Model-View-ViewModel), pierwsze co musimy zrobić to przekazać obiekt dispatcher'a do ViewModelu, np w konstruktorze:

private Dispatcher currentDispatcher;

public ViewModel(Dispatcher currentDispatcher)
{
    this.currentDispatcher = currentDispatcher;
}
Następnie aby dodawać obiekty do kolekcji CollectionViewSource, należy wykonać następujący kod:
currentDispatcher.Invoke(new Action(()=>
{
    this.collectionViewSource.Add(someObject);
}));

piątek, 11 kwietnia 2014

Database schema modeling - SQL Server Data Tools!

Post ku pamięci. Czy zdarzyło wam się kiedykolwiek, że mieliście 2 bazy danych, w których musieliście porównać ich schemę? Ja ostatnio miałem taką zagwozdkę, robiłem nową funkcjonalność i przepadł mi gdzieś skrypt, który uaktualniałby schemę bazy danych. Wiedziałem, że są pewne narzędzia, które by mi pomogły jednak nie chciałem korzystać z narzędzi firm trzecich. Poszperałem trochę w necie i okazało się, że Microsoft zrobił takie narzędzie. Nazywa się SQL Server Data Tools. Dzięki temu narzędzi możemy porównać sobie schemę dwóch baz, a nawet wygenerować skrypt zmian, który uaktualni nam naszą bazę danych.



SQL Server Data Tools jest dostarczane razem z Visual Studio 2013, jest możliwość dociągniecia instalki również do Visual Studio 2010 i Visual Studio 2012. Konkretną wersję można ściągnąć tutaj
http://blogs.technet.com/b/dataplatforminsider/archive/2013/11/13/microsoft-sql-server-data-tools-update.aspx

Co oferuje nam jeszcze to narzędzie? Możemy oczywiście graficznie modelować sobie naszą bazę danych. Mało tego narzędzie umożliwia nam nawet porównać dane w obu bazach za pomocą opcji "Data comparision" oraz tworzyć unit testy naszej bazy: więcej informacji znajdziemy tutaj

poniedziałek, 10 marca 2014

Szukanie procedury składowanej zawierającej ciąg znaków

Ostatnio zdarzyło mi się, że musiałem znaleźć wszystkie procedury składowane zawierające słowo "external". O tyle ważne, że w SQL Server 2012 jest to zarezerwowane słowo kluczowe a nasza baza danych, która wcześniej nie działała na SQL Server 2012 dość liberalnie podchodziła do użycia słowa "external" w procedurach składowanych m.in. nie zapisując nazwy tabeli o nazwie "external" w nawiasy kwadratowe. Czyli zamiast dbo.NazwaTabeli.[External] było dbo.NazwaTabeli.External. Przy takim zapisie program wywalał się wykonując procedurę składowaną na SQL Server 2012. 
Aby zatem znaleźć procedury składowane zawierające pewien ciąg znaków, można wykorzystać taki kod:

SELECT DISTINCT o.name AS Object_Name,o.type_desc
FROM sys.sql_modules m 
INNER JOIN sys.objects o 
ON m.object_id=o.object_id
WHERE m.definition Like '%external%'
order by Object_Name

czwartek, 6 marca 2014

Czyszczenie ClickOnce application cache bez mage.exe

Dawno temu kiedy zaczynałem przygodę z ClickOnce stworzyłem skrypcik, która czyścił application cache.
Generalnie wykorzystywała ona plik mage.exe w następujący sposób:

mage.exe -cc

Okazuje się, iż jest możliwość wyczyszczenia application cache dla ClickOnce bez potrzeby korzystania z aplikacji mage.exe
Wystarczy w oknie komend wpisać następującą komendę:

rundll32 dfshim CleanOnlineAppCache

EDIT:
Wygląda na to, iż powyższa komenda nie czyści jednak application cache. 
Ktoś na forum stackoverflow napisał, że działa ona tak samo jak mage.exe -cc:
I wanted to add the posters comment to my answer so people don't miss it. You don't have to have mage installed to clear the cache; running rundll32 dfshim CleanOnlineAppCache from the command line accomplishes the same thing as mage -cc.
Jednak z własnego doświadczenia muszę stwierdzić, że jednak nie. Nie jestem do końca pewien jaka jest różnica, gdy znajdę, na pewno to napiszę.

piątek, 7 lutego 2014

Kopiowanie zawartości jednej tabeli do drugiej

Załóżmy, że mamy dwie identyczne tabele, Table1, Table2. Table1 trzyma aktualne dane, Table2 dane historyczne. Ich struktura jest identyczna. Czasami zdarza się, że musimy przekopiować pewną ilość danych z jednej tabeli do drugiej. 
Można to zrobić następujących skryptem:

INSERT INTO Table1
SELECT * FROM Table2
WHERE some_condition

Bardzo prosty skrypcik. A piszę o nim ponieważ miałem z nim chwilę problem gdy napisałem go w takiej postaci (Z NAWIASAMI):
INSERT INTO Table1
(SELECT * FROM Table2
WHERE some_condition)

wtedy zapytanie wywala błąd. Prawdopodobnie dlatego, że oczekuje w nawiasach dokładnych parametrów a nie podzapytania.
Na szczęście szybko udało się rozwiązać problem. 

Wybieranie nazw kolumn w tabeli

Czasami zdarza się, że nasza tabela zawiera sporą ilość kolumn a my musimy wylistować wszystkie kolumny. Wiadomo, programista to leń i zawsze chce sobie ułatwić pracę. Dlatego poniższy skrypt już nie raz był przeze mnie używany. Wybiera on wszystkie kolumny z danej tabeli:

SELECT COLUMN_NAME, *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'YOUR_TABLE_NAME'