Integration Services i błąd DTS_E_CANNOTACQUIRECONNECTIONFROMCONNECTIONMANAGER

Dziś pisząc pewien pakiet integracyjny (integration services) napotkałem na następujący błąd:

Error: SSIS Error Code DTS_E_CANNOTACQUIRECONNECTIONFROMCONNECTIONMANAGER.  The AcquireConnection method call to the connection manager "Excel Connection Manager 1" failed with error code 0xC00F9304.  There may be error messages posted before this with more information on why the AcquireConnection method call failed.

Stworzony pakiet składał się z Excel Source. Po odpaleniu wystąpił błąd właśnie na tym elemencie. Przyczyną okazało się brak wsparcia dla procesorów 64-bitowych. Rozwiązaniem jest ustawienie właściwości Run64BitRuntime na false. Z menu głównego klikamy na Project->Properties i w otwartym oknie ustawiamy właściwość na false:

image

ASP.NET MVC i stronicowanie wyników

W ASP.NET MVC nie ma wbudowanego wsparcia stronicowania dla wyświetlanych danych. W czystym ASP .NET mieliśmy do dyspozycji wiele zaawansowanych kontrolek, które wspierały mechanizm stronicowania (np. ListView). W ASP.NET MVC interfejs definiujemy za pomocą czystego HTML\XHTML i sami musimy zadbać o możliwość stronicowania. Nie jest to trudne ale wymaga jednak trochę nakładu pracy. Jeśli chcemy mieć elastyczną bibliotekę do obsługi stronicowania to implementacja jest już dość czasochłonna. Dlatego w tym poście przedstawię gotową bibliotekę MvcPager załatwiająca większość rzeczy za nas. Niezbędne pliki możecie pobrać ze strony projektu tutaj. 

Po ściągnięciu plików należy najpierw dodać bibliotekę MVCPager do referencji. Następnie w widoku, który chcemy użyć stronicowania niezbędne jest zaimportowanie biblioteki za pomocą dyrektywy import:

<%@ Import Namespace="Webdiyer.WebControls.Mvc"%>

Następnie można wygenerować elementy graficzne odpowiedzialne za stronicowanie:

<%=Html.Pager(Model, new PagerOptions
{
    
    CurrentPagerItemWrapperFormatString = "<span class=\"cpb\">{0}</span>",    
    NumericPagerItemWrapperFormatString = "<span class=\"item\">{0}</span>",   
    CssClass = "pages",
    PageIndexParameterName = "quotePageIndex",
    NextPageText = ">>>",   
    PrevPageText = "<<<",
    ShowDisabledPagerItems = false,
    FirstPageText = "Pierwszy",
    SeparatorHtml = "" ,
    NumericPagerItemCount=5,
    LastPageText = "Ostatni"
}, "quotes")
    %>

Jak widać biblioteka umożliwia bardzo dokładną konfiguracje. Programista może m.in. określić wykorzystywany styl css lub ilość wyników na pojedynczej stronie. W funkcji Pager jako pierwszy parametr przekazuje się kolekcję danych a konkretnie Webdiyer.WebControls.Mvc.PagedList. Aby stronicowanie działało koniecznie musimy wykorzystać ten konkrety typ ale istnieje konwerter, który umożliwia łatwą zamianę np. IQueryable na PagedList:

Webdiyer.WebControls.Mvc.PagedList<Entities.Quote> quotes=null;
// quotes to IQueryable
pagedQuotes = quotes.ToPagedList(colDefs.QuotePageIndex, colDefs.PageSize);

image

W wyniku powyższego kodu dostaniemy stronicowanie pokazane na screenie. Implementacja samodzielna wcale nie jest taka prosta – głównie ze względu na wyświetlanie numerów stron. Poza tym poco męczyć się z czymś co jest już od dawna rozwiązane i dostępne publicznie za darmo?

ASP.NET MVC, Html.Editor(…), Html.EditorFor(…)

W poprzednim poście przedstawiłem metodę Html.Display. Funkcja Html.Editor(…) w działaniu jest bardzo podobna – również służy do generowania szablonów na podstawie klas. Różnica polega na tym, że Html.Editor tworzy pola edycyjne TextBox. Służy więc do generowania formularzy edycyjnych a nie do prezentowania danych tak jak Html.Display. Sposób wykorzystania jest analogiczny do DisplayFor więc zachęcam do przeczytania poprzedniego wpisu. Poniżej końcowy wynik:

image

Warto wspomnieć, że również można tworzyć własne szablony. Umieszczać należy je w formie widoków częściowych w folderze EditorTemplates (zamiast DisplayTemplates).

ASP .NET MVC, Html.Display(…), Html.DisplayFor(…)

Podczas budowania formularzy często potrzebujemy wyświetlić zbiory danych. Załóżmy, że mamy klasę Contact zawierającą dane kontaktowe użytkownika (email, telefon, fax). W celu wyświetlenia informacji zawartych w klasie można oczywiście użyć zwykłych wywołań Html.Label np:

<p>Phone:</p><%=Model.Contact.Phone%>
<p>Email:</p><%=Model.Contact.Email%>
<p>Fax:</p><%=Model.Contact.Fax%>

Metoda całkowicie poprawna jednak bardzo niewygodna – co jeśli do klasy dodamy nowe pole, np. MobilePhoneNumber? Oczywiście programista będzie musiał modyfikować kod – mało interesująca opcja. Na szczęście ASP .NET MVC dostarcza funkcję Display, która wyświetli wszystkie właściwości:

<%=Html.Display("Contact")%>

ViewData[“Contact”] musi zawierać oczywiście instancję klasy Contact:

Contact contact = new Contact();
contact.Email = "contact@live.com";
contact.Fax = "252525";
contact.Phone = "45353";

ViewData["Contact"] = contact;

Dla ścisłości dołączam jeszcze deklarację Contact:

[MetadataType(typeof(Contact_Metadata))]
public class Contact 
{
   public string Phone { get; set; }
   public string Fax { get; set; }
   public string Email { get; set; }
}

Warto zwrócić uwagę na atrybut MetadataType. Dzięki niemu możemy zdefiniować właściwości pól (długość, typ itp):

internal class Contact_Metadata
{
   [Required(ErrorMessage = "Phone is required.")]        
   public string Phone { get; set; }
   
   [Required(ErrorMessage = "Fax is required.")]
   public string Fax { get; set; }

   [Required(ErrorMessage = "Email is required.")]
   [StringLength(200, ErrorMessage = "Email must be 200 characters or less.")]
   [RegularExpression(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = "Valid Email Address is required.")]
   [DataType(DataType.EmailAddress)]
   public string Email { get; set; }

}

Jak wspomniałem Html.Display wyświetli wszystkie pola klasy:

image

Na tym jednak nie koniec zalet płynących z wykorzystania Display. Można definiować własne szablony dla poszczególnych pól. Szablony w formie widoków częściowych należy umieszczać w folderze DisplayTemplates np:

image

Przykładowy szablon dla pola Email (dodaje element graficzny):

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>

<a href="mailto:<%= Html.DisplayFor(emailaddress => emailaddress) %>">
    <%= Html.DisplayFor(emailaddress => emailaddress) %>
</a>
<img src="/Content/email.gif" />

W analogiczny sposób można definiować szablony dla całej klasy Contact a nie tylko dla poszczególnych pól. W tym celu dodajemy widok częściowy Contact.ascx i umieszczamy go również w DisplayTemplates:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcApplication2.Contact>" %>

<p>
    <%= Html.LabelFor(c => c.Phone)%>:
    <%= Html.DisplayFor(c => c.Phone)%>
</p>
<p>
    <%= Html.LabelFor(c => c.Email) %>:
    <%= Html.DisplayFor(c => c.Email) %>
</p>
<p>
    <%= Html.LabelFor(c => c.Fax) %>:
    <%= Html.DisplayFor(c => c.Fax) %>
</p>

GROUPBY i WITH CUBE

W poprzednim poście wyjaśniłem do czego służy klauzula WITH ROLLUP. Dzisiaj zajmiemy się bardzo podobnym mechanizmem – WITH CUBE. Najlepiej wyjaśnić to znów na przykładzie tabeli. Załóżmy, że mamy poniższe zapytanie:

select StoreName,ProductType,sum(Number) from SoldProducts GROUP BY  StoreName,ProductType

W wyniku wykonania otrzymamy:

StoreName ProductType Suma
SklepA komputery 1
SklepA spożywka 3
SklepB komputery 4
SklepB spożywka 6

Jak wiemy z poprzedniego wpisu WITH ROLLUP umożliwi uzyskanie wyników hierarchicznych (ile całkowicie zostało sprzedanych produktów w danym sklepie):

StoreName ProductType Suma
SklepA komputery 1
SklepA spożywka 3
SklepB komputery 4
SklepB spożywka 6
SklepA NULL 4
SklepB NULL 10
NULL NULL 14

 

Z kolei WITH CUBE zwróci trochę więcej wierszy:

select StoreName,ProductType,sum(Number) from SoldProducts GROUP BY  StoreName,ProductType WITH CUBE

StoreName ProductType Suma
SklepA komputery 1
SklepA spożywka 3
SklepB komputery 4
SklepB spożywka 6
SklepA NULL 4
SklepB NULL 10
NULL NULL 14
NULL spożywka 9
NULL komputery 5

Jak widać WITH CUBE stanowi rozszerzenie WITH ROLLUP – oprócz przedstawiania wyników hierarchicznych po pierwszej kolumnie również w wynikach uwzględnia się kategoryzowanie po drugiej kolumnie.

GROUP BY i WITH ROLLUP

Operator WITH ROLLUP używa się w połączeniu z GROUPBY. Czasami istnieje potrzeba grupowania wyników po dwóch kolumnach. Wyobraźmy sobie, że mamy tabelę lub widok zawierający listę sprzedanych produktów. Będziemy mieli zatem takie kolumny jak “nazwa produktu”, “nazwa sklepu w którym został sprzedany produkt” oraz “typ produktu”. Przykładowe zapytanie wyglądałoby więc następująco:

select StoreName,ProductType,sum(Number) from SoldProducts GROUP BY  StoreName,ProductType

Zapytanie zwróci produkty pogrupowanie wzgędem sklepu oraz typu:

StoreName ProductType Suma
SklepA komputery 1
SklepA spożywka 3
SklepB komputery 4
SklepB spożywka 6

Po wynikach wiemy jaka grupa produktów sprzedaje się najlepiej w danym sklepie. Za pomocą WITH ROLLUPP możemy dowiedzieć się również ile sztuk produktu zostało sprzedanych w danym sklepie, niezależnie od jego typu:

select StoreName,ProductType,sum(Number) from SoldProducts GROUP BY  StoreName,ProductType WITH ROLLUP

StoreName ProductType Suma
SklepA komputery 1
SklepA spożywka 3
SklepB komputery 4
SklepB spożywka 6
SklepA NULL 4
SklepB NULL 10
NULL NULL 14

Jak widać, WITH ROLLUP spowodował dodanie hierarchicznych wierzy z NULL. Wiadomo, teraz ile ogólnie zostało sprzedanych produktów oraz ile w poszczególnych sklepach.