Dodawanie dodatkowych kolumn tabeli DataTable (C#)

Autor: Scott Mitchell

Pobierz plik PDF

W przypadku korzystania z Kreatora tableAdapter do utworzenia typu zestawu danych odpowiedni obiekt DataTable zawiera kolumny zwrócone przez główne zapytanie bazy danych. Istnieją jednak sytuacje, w których tabela DataTable musi zawierać dodatkowe kolumny. W tym samouczku dowiesz się, dlaczego procedury składowane są zalecane, gdy potrzebujemy dodatkowych kolumn dataTable.

Wprowadzenie

Podczas dodawania elementu TableAdapter do typu zestawu danych odpowiedni schemat dataTable jest określany przez główne zapytanie TableAdapter. Jeśli na przykład główne zapytanie zwraca pola danych A, B i C, tabela DataTable będzie zawierać trzy odpowiednie kolumny o nazwach A, B i C. Oprócz głównego zapytania tabelaAdapter może zawierać dodatkowe zapytania, które zwracają, być może, podzbiór danych na podstawie określonego parametru. Na przykład oprócz ProductsTableAdapter głównego zapytania, które zwraca informacje o wszystkich produktach, zawiera również metody, takie jak GetProductsByCategoryID(categoryID) i GetProductByProductID(productID), które zwracają określone informacje o produkcie na podstawie podanego parametru.

Model schematu tabeli DataTable odzwierciedla główne zapytanie TableAdapter działa dobrze, jeśli wszystkie metody TableAdapter zwracają te same lub mniej pól danych niż te określone w zapytaniu głównym. Jeśli metoda TableAdapter musi zwrócić dodatkowe pola danych, należy odpowiednio rozwinąć schemat tabeli danych DataTable. W temacie Master/Detail Using a Bulleted List of Master Records with a Details DataList tutorial (Szczegóły DataList) dodaliśmy metodę do CategoriesTableAdapter zwracanych CategoryIDpól , CategoryNamei Description danych zdefiniowanych w zapytaniu głównym oraz NumberOfProducts, dodatkowe pole danych, które zgłosiło liczbę produktów skojarzonych z każdą kategorią. Ręcznie dodaliśmy nową kolumnę do CategoriesDataTable obiektu w celu przechwycenia NumberOfProducts wartości pola danych z tej nowej metody.

Zgodnie z opisem w samouczku Przekazywanie plików należy zadbać o to, aby elementy TableAdapters używały instrukcji AD-hoc SQL i miały metody, których pola danych nie są dokładnie zgodne z głównym zapytaniem. Jeśli kreator konfiguracji tableAdapter zostanie ponownie uruchomiony, zaktualizuje wszystkie metody tableAdapter tak, aby ich lista pól danych była zgodna z głównym zapytaniem. W związku z tym wszystkie metody z dostosowanymi listami kolumn zostaną przywrócone do głównej listy kolumn zapytania i nie zwracają oczekiwanych danych. Ten problem nie występuje podczas korzystania z procedur składowanych.

W tym samouczku przyjrzymy się sposobom rozszerzania schematu tabeli danych w celu uwzględnienia dodatkowych kolumn. Ze względu na kruchość instrukcji TableAdapter podczas korzystania z instrukcji AD-hoc SQL w tym samouczku będziemy używać procedur składowanych. Aby uzyskać więcej informacji na temat konfigurowania obiektu TableAdapters zestawu danych typowych, zapoznaj się z samouczkiem Tworzenie nowych procedur składowanych zestawu danych .

Krok 1. Dodawanie kolumnyPriceQuartiledo elementuProductsDataTable

W samouczku Tworzenie nowych procedur składowanych dla typowych zestawów danych TableAdapters utworzyliśmy typowy zestaw danych o nazwie NorthwindWithSprocs. Ten zestaw danych zawiera obecnie dwie tabele danych: ProductsDataTable i EmployeesDataTable. Ma ProductsTableAdapter następujące trzy metody:

  • GetProducts — główne zapytanie, które zwraca wszystkie rekordy z Products tabeli
  • GetProductsByCategoryID(categoryID) — zwraca wszystkie produkty o określonym identyfikatorze categoryID.
  • GetProductByProductID(productID) — zwraca określony produkt o określonym identyfikatorze productID.

Główne zapytanie i dwie dodatkowe metody zwracają ten sam zestaw pól danych, a mianowicie wszystkie kolumny z Products tabeli. Nie ma skorelowanych podquerii ani JOIN ściągania powiązanych danych z Categories tabel lub Suppliers . W związku z tym kolumna ProductsDataTable zawiera odpowiednią kolumnę dla każdego pola w Products tabeli.

Na potrzeby tego samouczka dodajmy metodę do ProductsTableAdapter nazwanej, GetProductsWithPriceQuartile która zwraca wszystkie produkty. Oprócz standardowych pól GetProductsWithPriceQuartile danych produktu będzie również zawierać PriceQuartile pole danych, które wskazuje, w którym kwartylu spada cena produktu. Na przykład te produkty, których ceny są w najdroższych 25% będą miały PriceQuartile wartość 1, podczas gdy te, których ceny spadną dolnej 25%, będą miały wartość 4. Zanim jednak zaczniemy martwić się o utworzenie procedury składowanej w celu zwrócenia tych informacji, najpierw musimy zaktualizować ProductsDataTable element , aby uwzględnić kolumnę w celu przechowywania PriceQuartile wyników podczas GetProductsWithPriceQuartile używania metody.

Otwórz element NorthwindWithSprocs DataSet i kliknij prawym przyciskiem myszy element ProductsDataTable. Wybierz pozycję Dodaj z menu kontekstowego, a następnie wybierz pozycję Kolumna.

Dodawanie nowej kolumny do tabeli ProductsDataTable

Rysunek 1. Dodawanie nowej kolumny do elementu ProductsDataTable (kliknij, aby wyświetlić obraz pełnowymiarowy)

Spowoduje to dodanie nowej kolumny do tabeli danych o nazwie Column1 typu System.String. Musimy zaktualizować nazwę tej kolumny na PriceQuartile i jej typ, ponieważ będzie ona używana do przechowywania liczby z zakresu od 1 do System.Int32 4. Wybierz nowo dodaną kolumnę w ProductsDataTable obiekcie i z okno Właściwości ustaw Name właściwość na PriceQuartile i DataType właściwość na System.Int32.

Ustawianie właściwości Nazwa nowej kolumny i Typ danych

Rysunek 2. Ustawianie właściwości nowej kolumny Name i DataType (kliknij, aby wyświetlić obraz pełnowymiarowy)

Jak pokazano na rysunku 2, istnieją dodatkowe właściwości, które można ustawić, takie jak to, czy wartości w kolumnie muszą być unikatowe, jeśli kolumna jest kolumną automatycznego zwiększania, niezależnie od tego, czy wartości bazy danych NULL są dozwolone itd. Pozostaw te wartości ustawione na wartości domyślne.

Krok 2. TworzenieGetProductsWithPriceQuartilemetody

Teraz, gdy element ProductsDataTable został zaktualizowany w celu uwzględnienia PriceQuartile kolumny, możemy przystąpić do tworzenia GetProductsWithPriceQuartile metody. Zacznij od kliknięcia prawym przyciskiem myszy pozycji TableAdapter i wybrania pozycji Dodaj zapytanie z menu kontekstowego. Spowoduje to wyświetlenie kreatora konfiguracji zapytań TableAdapter, który najpierw monituje nas o to, czy chcemy użyć instrukcji AD-hoc SQL, czy nowej lub istniejącej procedury składowanej. Ponieważ nie mamy jeszcze procedury składowanej, która zwraca dane kwartylu cen, pozwólmy tableAdapter utworzyć dla nas tę procedurę składowaną. Wybierz opcję Utwórz nową procedurę składowaną i kliknij przycisk Dalej.

Poinstruuj Kreatora tableAdapter, aby utworzyć procedurę składowaną dla nas

Rysunek 3. Poinstruuj Kreatora tableAdapter, aby utworzyć procedurę składowaną dla nas (kliknij, aby wyświetlić obraz pełnowymiarowy)

Na kolejnym ekranie pokazanym na rysunku 4 kreator pyta nas o typ zapytania do dodania. GetProductsWithPriceQuartile Ponieważ metoda zwróci wszystkie kolumny i rekordy z Products tabeli, wybierz opcję SELECT, która zwraca wiersze, a następnie kliknij przycisk Dalej.

Zapytanie będzie instrukcją SELECT zwracającą wiele wierszy

Rysunek 4. Zapytanie będzie instrukcją zwracającą SELECT wiele wierszy (kliknij, aby wyświetlić obraz pełnowymiarowy)

Następnie zostanie wyświetlony monit o SELECT podanie zapytania. Wprowadź następujące zapytanie w kreatorze:

SELECT ProductID, ProductName, SupplierID, CategoryID, 
       QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, 
       ReorderLevel, Discontinued,
       NTILE(4) OVER (ORDER BY UnitPrice DESC) as PriceQuartile
FROM Products

Powyższe zapytanie używa nowej NTILE funkcji SQL Server 2005, aby podzielić wyniki na cztery grupy, w których grupy są określane według UnitPrice wartości posortowanych w kolejności malejącej.

Niestety konstruktor zapytań nie wie, jak przeanalizować OVER słowo kluczowe i wyświetli błąd podczas analizowania powyższego zapytania. W związku z tym wprowadź powyższe zapytanie bezpośrednio w polu tekstowym w kreatorze bez użycia konstruktora zapytań.

Uwaga

Aby uzyskać więcej informacji na temat funkcji NTILE i SQL Server 2005 innych funkcji klasyfikacji, zobacz ROW_NUMBER (Transact-SQL) i sekcję Funkcje klasyfikacji z SQL Server 2005 Books Online.

Po wprowadzeniu zapytania i kliknięciu SELECT przycisku Dalej kreator poprosi nas o podanie nazwy procedury składowanej, która zostanie utworzona. Nadaj nowej procedurze Products_SelectWithPriceQuartile składowanej nazwę i kliknij przycisk Dalej.

Nadaj nazwę procedurze składowanej Products_SelectWithPriceQuartile

Rysunek 5. Nadaj nazwę procedurze Products_SelectWithPriceQuartile składowanej (kliknij, aby wyświetlić obraz pełnowymiarowy)

Na koniec zostanie wyświetlony monit o nadenie nazwy metod TableAdapter. Pozostaw zaznaczone pola wyboru Wypełnij tabelę danych i Zwracaj tabelę danych oraz nazwij metody FillWithPriceQuartile i GetProductsWithPriceQuartile.

Nadaj metodom TableAdapter nazwę i kliknij przycisk Zakończ

Rysunek 6. Nadaj nazwę metod tableAdapter i kliknij przycisk Zakończ (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po określeniu SELECT zapytania oraz procedurze składowanej i metodach TableAdapter o nazwie kliknij przycisk Zakończ, aby ukończyć pracę kreatora. W tym momencie może zostać wyświetlone ostrzeżenie lub dwa z kreatora z informacją, że OVER konstrukcja lub instrukcja SQL nie jest obsługiwana. Te ostrzeżenia można zignorować.

Po ukończeniu pracy kreatora narzędzie TableAdapter powinno zawierać FillWithPriceQuartile metody i GetProductsWithPriceQuartile , a baza danych powinna zawierać procedurę składowaną o nazwie Products_SelectWithPriceQuartile. Poświęć chwilę, aby sprawdzić, czy tabela TableAdapter rzeczywiście zawiera tę nową metodę i że procedura składowana została poprawnie dodana do bazy danych. Jeśli podczas sprawdzania bazy danych nie widzisz procedury składowanej, spróbuj kliknąć prawym przyciskiem myszy folder Procedury składowane i wybrać polecenie Odśwież.

Sprawdź, czy nowa metoda została dodana do tabeli TableAdapter

Rysunek 7. Sprawdź, czy nowa metoda została dodana do tabeli TableAdapter

Upewnij się, że baza danych zawiera procedurę składowaną Products_SelectWithPriceQuartile

Rysunek 8. Upewnij się, że baza danych zawiera procedurę Products_SelectWithPriceQuartile składowaną (kliknij, aby wyświetlić obraz pełnowymiarowy)

Uwaga

Jedną z zalet korzystania z procedur składowanych zamiast instrukcji ad hoc SQL jest to, że ponowne uruchomienie kreatora konfiguracji TableAdapter nie spowoduje modyfikacji list kolumn procedur składowanych. Sprawdź to, klikając prawym przyciskiem myszy tabelę TableAdapter, wybierając opcję Konfiguruj z menu kontekstowego, aby uruchomić kreatora, a następnie klikając przycisk Zakończ, aby go ukończyć. Następnie przejdź do bazy danych i wyświetl procedurę Products_SelectWithPriceQuartile składowaną. Należy pamiętać, że lista kolumn nie została zmodyfikowana. Gdyby używaliśmy instrukcji AD-hoc SQL, ponownie uruchomiono kreatora konfiguracji TableAdapter, przywróciłoby listę kolumn zapytania, aby dopasować listę kolumn zapytania do listy kolumn głównych zapytań, usuwając w ten sposób instrukcję NTILE z zapytania używanego przez metodę GetProductsWithPriceQuartile .

Po wywołaniu metody warstwy GetProductsWithPriceQuartile dostępu do danych metoda TableAdapter wykonuje Products_SelectWithPriceQuartile procedurę składowaną i dodaje wiersz do ProductsDataTable każdego zwróconego rekordu. Pola danych zwracane przez procedurę składowaną są mapowane na ProductsDataTable kolumny. Ponieważ istnieje PriceQuartile pole danych zwracane z procedury składowanej, jego wartość jest przypisywana do ProductsDataTable kolumny s PriceQuartile .

Dla tych metod TableAdapter, których zapytania nie zwracają PriceQuartile pola danych, PriceQuartile wartość kolumny jest wartością określoną przez jej DefaultValue właściwość. Jak pokazano na rysunku 2, ta wartość jest ustawiona na DBNullwartość , wartość domyślna. Jeśli wolisz inną wartość domyślną, po prostu ustaw DefaultValue właściwość odpowiednio. Upewnij się, że DefaultValue wartość jest prawidłowa, biorąc pod uwagę kolumny DataType (tj System.Int32 . dla kolumny PriceQuartile ).

Na tym etapie wykonaliśmy kroki niezbędne do dodania dodatkowej kolumny do tabeli DataTable. Aby sprawdzić, czy ta dodatkowa kolumna działa zgodnie z oczekiwaniami, utwórzmy stronę ASP.NET, która wyświetla nazwę, cenę i kwartyl każdego produktu. Zanim to zrobimy, najpierw musimy zaktualizować warstwę logiki biznesowej, aby uwzględnić metodę, która wywołuje metodę dal w dół do metody DAL GetProductsWithPriceQuartile . Następnie zaktualizujemy BLL w kroku 3, a następnie utworzymy stronę ASP.NET w kroku 4.

Krok 3. Rozszerzanie warstwy logiki biznesowej

Przed użyciem nowej GetProductsWithPriceQuartile metody z warstwy prezentacji należy najpierw dodać odpowiednią metodę do BLL. ProductsBLLWithSprocs Otwórz plik klasy i dodaj następujący kod:

[System.ComponentModel.DataObjectMethodAttribute
    (System.ComponentModel.DataObjectMethodType.Select, false)]
public NorthwindWithSprocs.ProductsDataTable GetProductsWithPriceQuartile()
{
    return Adapter.GetProductsWithPriceQuartile();
}

Podobnie jak inne metody pobierania danych w ProductsBLLWithSprocsmetodzie , GetProductsWithPriceQuartile metoda po prostu wywołuje odpowiednią GetProductsWithPriceQuartile metodę DAL i zwraca jej wyniki.

Krok 4. Wyświetlanie informacji kwartylu cen na stronie internetowej ASP.NET

Po zakończeniu dodawania BLL możemy utworzyć stronę ASP.NET, która pokazuje kwartyl cen dla każdego produktu. AddingColumns.aspx Otwórz stronę w folderze AdvancedDAL i przeciągnij kontrolkę GridView z przybornika do Projektant, ustawiając jej ID właściwość na Products. Z tagu inteligentnego GridView powiąż go z nowym obiektem ObjectDataSource o nazwie ProductsDataSource. Skonfiguruj obiekt ObjectDataSource do używania ProductsBLLWithSprocs metody s GetProductsWithPriceQuartile klasy. Ponieważ będzie to siatka tylko do odczytu, ustaw listy rozwijane na kartach UPDATE, INSERT i DELETE na wartość (Brak).

Konfigurowanie obiektu ObjectDataSource do używania klasy ProductsBLLWithSprocs

Rysunek 9. Konfigurowanie obiektu ObjectDataSource do używania ProductsBLLWithSprocs klasy (kliknij, aby wyświetlić obraz pełnowymiarowy)

Pobieranie informacji o produkcie z metody GetProductsWithPriceQuartile

Rysunek 10. Pobieranie informacji o produkcie GetProductsWithPriceQuartile z metody (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po ukończeniu pracy kreatora Konfigurowanie źródła danych program Visual Studio automatycznie doda pole BoundField lub CheckBoxField do kontrolki GridView dla każdego pola danych zwracanego przez metodę . Jedno z tych pól danych to PriceQuartile, czyli kolumna dodana do ProductsDataTable kroku 1.

Edytuj pola kontrolki GridView, usuwając wszystkie ProductNamepola , UnitPricei PriceQuartile BoundFields. Skonfiguruj pole UnitPrice BoundField, aby sformatować jego wartość jako walutę i odpowiednio UnitPrice wyrównać do środka i PriceQuartile pola BoundFields. Na koniec zaktualizuj pozostałe właściwości BoundFields HeaderText odpowiednio do właściwości Product, Price i Price Quartile. Zaznacz również pole wyboru Włącz sortowanie z tagu inteligentnego GridView.

Po tych modyfikacjach znaczniki deklaratywne gridView i ObjectDataSource powinny wyglądać następująco:

<asp:GridView ID="Products" runat="server" AllowSorting="True"
    AutoGenerateColumns="False" DataKeyNames="ProductID" 
    DataSourceID="ProductsDataSource">
    <Columns>
        <asp:BoundField DataField="ProductName" HeaderText="Product" 
            SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}" 
            HeaderText="Price" HtmlEncode="False" 
            SortExpression="UnitPrice">
            <ItemStyle HorizontalAlign="Right" />
        </asp:BoundField>
        <asp:BoundField DataField="PriceQuartile" HeaderText="Price Quartile" 
            SortExpression="PriceQuartile">
            <ItemStyle HorizontalAlign="Center" />
        </asp:BoundField>
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProductsWithPriceQuartile" 
    TypeName="ProductsBLLWithSprocs">
</asp:ObjectDataSource>

Rysunek 11 przedstawia tę stronę po odwiedzeniu za pośrednictwem przeglądarki. Należy pamiętać, że początkowo produkty są uporządkowane według ich ceny w kolejności malejącej, a każdy produkt ma przypisaną odpowiednią PriceQuartile wartość. Oczywiście te dane można sortować według innych kryteriów z wartością kolumny kwartylu cen nadal odzwierciedlając klasyfikację produktu w odniesieniu do ceny (patrz Rysunek 12).

Produkty są uporządkowane według ich cen

Rysunek 11. Produkty są uporządkowane według ich cen (kliknij, aby wyświetlić obraz pełnowymiarowy)

Produkty są uporządkowane według ich nazw

Rysunek 12. Produkty są uporządkowane według ich nazw (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Uwaga

Za pomocą kilku wierszy kodu możemy rozszerzyć obiekt GridView, tak aby wiersze produktów zostały kolorowe na podstawie ich PriceQuartile wartości. Możemy kolorować te produkty w pierwszym kwartylu jasnozielony, te w drugim kwartylu jasnożółtym i tak dalej. Zachęcam do poświęć chwilę, aby dodać tę funkcjonalność. Jeśli potrzebujesz modułu odświeżania podczas formatowania kontrolki GridView, zapoznaj się z samouczkiem Custom Formatting Based Data (Formatowanie niestandardowe oparte na danych ).

Alternatywne podejście — tworzenie innego elementu TableAdapter

Jak pokazano w tym samouczku, podczas dodawania metody do kontrolki TableAdapter, która zwraca pola danych inne niż te zapisane przez zapytanie główne, możemy dodać odpowiednie kolumny do tabeli DataTable. Takie podejście sprawdza się jednak tylko wtedy, gdy w metodzie TableAdapter istnieje niewielka liczba metod, które zwracają różne pola danych i jeśli te alternatywne pola danych nie różnią się zbytnio od zapytania głównego.

Zamiast dodawać kolumny do tabeli DataTable, możesz zamiast tego dodać inny element TableAdapter do zestawu danych, który zawiera metody z pierwszego obiektu TableAdapter, który zwraca różne pola danych. W tym samouczku zamiast dodawać kolumnę PriceQuartile do ProductsDataTable obiektu (gdzie jest używana tylko przez GetProductsWithPriceQuartile metodę), możemy dodać dodatkowy element TableAdapter do zestawu danych o nazwie ProductsWithPriceQuartileTableAdapter , który użył Products_SelectWithPriceQuartile procedury składowanej jako głównego zapytania. ASP.NET strony, które musiały uzyskać informacje o produkcie z kwartylem cen, będą używać ProductsWithPriceQuartileTableAdapterwartości , a te, które nie mogły nadal korzystać z elementu ProductsTableAdapter.

Dodając nowy element TableAdapter, tabele DataTable pozostają niezmienione, a ich kolumny dokładnie odzwierciedlają pola danych zwracane przez metody tableAdapter. Jednak dodatkowe elementy TableAdapters mogą wprowadzać powtarzające się zadania i funkcje. Jeśli na przykład te strony ASP.NET, które wyświetlały kolumnę PriceQuartile , również potrzebne do zapewnienia obsługi wstawiania, aktualizowania i usuwania, ProductsWithPriceQuartileTableAdapter muszą mieć odpowiednio InsertCommandskonfigurowane właściwości , UpdateCommandi DeleteCommand . Chociaż te właściwości dublowałyby ProductsTableAdapter s, ta konfiguracja wprowadza dodatkowy krok. Ponadto istnieją dwa sposoby aktualizowania, usuwania lub dodawania produktu do bazy danych — za pomocą ProductsTableAdapter klas i ProductsWithPriceQuartileTableAdapter .

Pobieranie dla tego samouczka zawiera klasę ProductsWithPriceQuartileTableAdapter w zestawie NorthwindWithSprocs danych, która ilustruje to alternatywne podejście.

Podsumowanie

W większości scenariuszy wszystkie metody w metodzie TableAdapter zwracają ten sam zestaw pól danych, ale istnieją sytuacje, w których określona metoda lub dwie mogą wymagać zwrócenia dodatkowego pola. Na przykład w samouczku Master/Detail Using a Bulleted List of Master Records with a Details DataList (Lista punktowana rekordów głównych z listą szczegółów dataList ) dodaliśmy metodę , CategoriesTableAdapter która oprócz pól danych zapytania głównego zwróciła NumberOfProducts pole, które zgłosiło liczbę produktów skojarzonych z każdą kategorią. W tym samouczku przyjrzeliśmy się dodawaniu metody w ProductsTableAdapter pole, które zwróciło PriceQuartile pole oprócz pól danych zapytania głównego. Aby przechwytywać dodatkowe pola danych zwracane przez metody tableAdapter, musimy dodać odpowiednie kolumny do tabeli DataTable.

Jeśli planujesz ręczne dodawanie kolumn do tabeli DataTable, zaleca się użycie procedur składowanych przez obiekt TableAdapter. Jeśli tableAdapter używa ad hoc instrukcji SQL, za każdym razem, gdy kreator konfiguracji tableAdapter zostanie uruchomiony wszystkie listy pól danych metod, zostaną przywrócone do pól danych zwracanych przez zapytanie główne. Ten problem nie obejmuje procedur składowanych, dlatego są one zalecane i były używane w tym samouczku.

Szczęśliwe programowanie!

Informacje o autorze

Scott Mitchell, autor siedmiu książek ASP/ASP.NET i założyciel 4GuysFromRolla.com, współpracuje z technologiami internetowymi firmy Microsoft od 1998 roku. Scott pracuje jako niezależny konsultant, trener i pisarz. Jego najnowsza książka to Sams Teach Yourself ASP.NET 2.0 w ciągu 24 godzin. Można do niego dotrzeć pod adresem mitchell@4GuysFromRolla.com. Lub za pośrednictwem swojego bloga, który można znaleźć na stronie http://ScottOnWriting.NET.

Specjalne podziękowania

Ta seria samouczków została przejrzyona przez wielu przydatnych recenzentów. Głównymi recenzentami tego samouczka byli Randy Schmidt, Jacky Goor, Bernadette Leigh i Hilton Giesenow. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresemmitchell@4GuysFromRolla.com .