Daily Archives: 2007.06.8. 18:52

SQL Server 2005 Compact Edition – első lépések

Van a Microsoftnak több adatkezelő motorja, ezek közül talán az SQL Server 2005 Compact Edition (SSCE) a legszimpatikusabb: ő egy in-process adatbázis motor (tehát nem service), mindössze 5 MB memória és 2 MB diszk igénnyel (a hivatalos adatok szerint). Persze vannak korlátai is, egy felhasználós, egy fájlos adatbázist tud kezelni és sajnos nem ismeri a tárolt eljárásokat, ami azért sajnálatos, mert ahogy május 24-én említettem, a LINQ to SQL egyelőre nem támogatja az SSCE-t. Azért még ezekkel a megkötésekkel is időnként jól jön egy olyan adatbázis motor, amit nem kell telepíteni, csak felmásolni a DLL-jeit, amihez az adatbázist nem kell attachelni, csak odamásolni és amit a szokásos SQL parancsokkal le tudunk kérdezni.

Íme egy kis segítség az első lépésekhez:

Mivel olvasott embernek párja nincs, legalább a 2 oldalas datasheetet érdemes elolvasni annak, aki még nem ismeri ezt a terméket. Kicsit hosszabb, de lényegesen hasznosabb a Data Storage Architecture doksi, azt inkább ajánlom.

Ha már elég tettrekésznek érezzük magunkat, akkor először is célszerű letölteni azt a csomagot, ami a Visual Studioba beépülő editor támogatást is tartalmazza.

Ha ez megvan és végignyomkodtuk a next-next-finish varázslót, ideje megkeresni a Studioban, hogyan is tudjuk hozzáadni ezt a szolgáltatást egy projektünkhöz. Mivel WinFormsos tutorialok vannak az MSDN-en, most inkább azt nézzük, hogy egy mezei konzol alkalmazásnál mit kell tennünk.

Az új alkalmazás létrehozása után kell egy referenciát adnunk a System.Data.SqlServerCe szerelvényre. Ennek a helye önmagában is érdekes:

  • Lehet a GAC-ban, mert – a leírás szerint legalábbis – a Microsoft MSI telepítője odateszi. Ha ott van, azért remek, mert onnan tud Windows Update-elődni.
  • Lehet a C:Program FilesMicrosoft Visual Studio 8Common7IDE vagy az alatt a PublicAssemblies mappában. A fene se érti mit keres itt, nálam ide települt.
  • Lehet bárhol, hiszen csak egy szerelvény referenciára van szükségünk.

A következő lépésben természetesen usingolni kell:

    using System.Data.SqlServerCe;

Ezek után a történet a szokásos, kell egy connection, annak egy connection string, ami ezúttal nem adatbázisra, hanem fájlra mutat. Egyébként érti az ASP.NET-ben megszokott |DataDirectory| formátumot is (@"Data Source = |DataDirectory|Northwind.sdf").

    SqlCeConnection conn = new SqlCeConnection( "Data Source=Northwind.sdf" );

SDF, mint single data file. Honnan lesz Northwind példafájlunk? Onnan, hogy megtaláljuk a C:Program FilesMicrosoft Visual Studio 8SmartDevicesSDKSQL ServerMobilev3.0 mappában. A fájlt hozzáadva a solutionhöz, majd duplán kattintva rá, tudjuk szerkeszteni a táblákat és az adatokat a Server Explorerben, csakúgy, mint a nagy SQL Server esetén. Ezzel kapcsolatban egy tapasztalat: ha a Server Explorerben nem zárjuk le a kapcsolatot, a Setup project nem veszi hozzá az SDF fájlt a telepítőhöz a setup project buildelése közben és persze hibaüzenetet sem küld.

Ezek után jöhet a command, ami nem lehet tárolt eljárás, de paraméterezett lekérdezés igen:

    SqlCeCommand cmd = new SqlCeCommand( 
"SELECT [Company Name], [Contact Name] FROM Customers WHERE City=@City", conn ); cmd.Parameters.AddWithValue( "@City", "London" );

A query megszülésében a VS tud segíteni: jobb klikk a Server Explorerben az adatbázison, majd a New Query menüpontot választva jön az ismerős Query Builder ablak, ahol összekattintgathatjuk, majd kikopipésztelhetjük az SQL lekérdezést.

Végül jön a szokásos megnyitás, futtatás, lezárás, ami mezei demó kódban így fest:

    conn.Open();

    SqlCeDataReader reader = cmd.ExecuteReader();
    while( reader.Read() )
    {
        Console.WriteLine( "{0,-30}{1}", reader[ "Company Name" ], reader[ "Contact Name" ] );
    }

    reader.Close();
    conn.Close();

Aki nem konzol alkalmazásból akarja használni, hanem mondjuk WinFormsban akar bűvészkedni, annak is gondja lehet azzal, hogy az Add New Item dialógus ablakban nem tud SDF fájlt hozzáadni a projekthez. A trükk az, hogy a Data -> Show Data Sources ablakból kell elindulni és fel kell venni egy új Database típusú adatforrást, aminek a konfigurálásakor Microsoft SQL Server 2005 Compact Editiont kell kiválasztani, ami után a következő ablakban már találunk egy Create gombot.

A Data Sources ablakból lehet egyébként ugyanúgy lehet varázsolgatni egy WinForms alkalmazásban, ahogy azt SQL Servernél vagy Expressnél megszoktuk, erről van itt néhány tutorial. Aki pedig a DataSet jellegű megközelítést szereti, az élvezkedhet az SqlCeResultSet osztállyal.

A fenti kódot tartalmazó projekt forráskódja a devPORTALról tölthető le.

Technorati tags: ,

Advertisements

Page Flow

A novemberi Foundationökről szóló MSDN konferencián említettem, hogy a Windows Workflow Foundation elméletben használható nem csak üzleti folyamatok, hanem felhasználói interakció vezérlésére is. Másként fogalmazva – és nagyban leegyszerűsítve – a UI kezelésére definiálunk folyamatokat, ez a page flow.

Akkor azt mondtam, hogy ennek implementálásán dolgoznak Redmondban és várhatóan lesz egy ilyen kiegészítés a WF-hez. Nos nem lesz, a szép kód, amit a TechEden mutattak tavaly, mindössze egy letölthető WF példakódban landolt. A kb. 4 MB-os telepítő a C:Program FilesWindows Workflow Foundation SamplesPageFlowSample mappába pakolja be magát és beregisztrál egy új projekt típust a VS-ba, amit a New Project -> Visual C# -> Workflow típusok között a (vigyázat!) My Templates csoportban találunk PageFlow néven.

Erre kattintva legenerálhatunk egy új projekt típust, ami nem csinál semmit, de legalább megnézhetjük, hogy mit kellett legyártaniuk Redmondban ahhoz, hogy ez a funkció megvalósuljon:

  • Új projekt típus
  • Új workflow típus (nem state machine és nem sequential, hanem NavigatorWorkflow) és ahhoz persze designer a Studioba
  • Új scheduler service (SynchronousSchedulerService)
  • Új activity (InteractionActivity), valamint ahhoz designer és validator
  • És sok más körítés (editor, type converter, toolbox item, exception, config section és egy csomó segédosztály)

A felsorolásból talán már lehet érezni, hogy a feladat lényegesen nagyobb, mint azt az ember elsőre gondolná. Példaként egy elég lightos ASP.NET alkalmazást kapunk, de a doksi szerint tud működni WPF-fel is. Apropó doksi, a telepítő mappában találjuk pageflowwhitepaper.doc néven, de érdemes átfutni a DOCSWF_UI_Workflow_Design_and_Implementation.doc fájlt is (egyikre sem készül link a Start menüben). Ugyanott találunk még példakódokat ÉÉÉÉÉS az egész implementációnak a forráskódját, amiben ugyan komment nem sok van, de mazsolázni lehet belőle!

Nem kis feladat megemészteni, de akit ennek ellenére mégis érdekel a téma, annak Matt Winkler blogját tudom ajánlani, ő ennek  a gazdája.

Technorati tags: , ,

Vista, te csodás

(Disclaimer: natív morgás, semmi több.)

Hónapok óta levelezgetek a Microsoft Supporttal, hogy miért nem képes a laptopomon lévő Vista alatt futni a Visual Studio 2005. Minden patch fent van, mégis amikor ki akarom nyitni a Toolboxot terminál a devenv processz, azt se mondja bikmakk. Annyira elszáll, hogy hibaüzenet sincs. Más is szív a Vistával, neki van hibaüzenet, biztosan sokat segít is:

error

Fogadni mernék, hogy egyszer majd megjelenik egy press release, hogy a Microsoft vonultatta fel a világon a legtöbb béta tesztelőt (bár ismerek még néhány egyetemi szoftvert, ami tutira versenyben lenne a címért). Megütne a guta, ha ezért a support szolgáltatásért vagy a szoftverekért nekem személyesen fizetnem kellene…

Ha valakinek van ötlete a megoldásra, kérem ne habozzon megosztani. Köszönöm!

Technorati tags:

Folyamatok dokumentálása saját activity designerrel

Az MSDN Kompetencia Központon belül a BME Információtechnológiai Innovációs és Tudásközpontjával együttműködve épp egy olyan e-dokumentumkezelési projekten dolgozunk, ahol a dokumentumok életciklusát Windows Workflow Foundation alapokon definiált folyamatok vezérlik. sok más mellett a Microsoft szerint a WF előnye, hogy a folyamatok a Visual Studio dizájnere segítségével grafikusan megjeleníthetőek, így a kód szinte önmagát dokumentálja.

Na ez pontosan addig igaz, amíg valaki egy kontroll ID-ja alapján tudja, hogy az mit csinál. A VS ugyanis így jeleníti meg a folyamatok minden egyes elemét, az ún. activity-ket:

Egy hosszú nevű activity

Az esetek többségében tehát az sem derül ki, hogy pontosan hogyan is hívják az adott activity-t, az meg aztán pláne nem, hogy mit csinál. Persze fölévihetem az egeret és akkor megjelenik a leírás tooltipben, de azt többek szerint aránylag nehézkes kinyomtatni.

A feladat tehát az, hogy a VS által rajzolt ábrát használható formára kell hozni. Erre a legkézenfekvőbb lehetőség, ha készítünk egy saját activity designer osztályt, ami meghatározza, hogyan jelenjen meg az adott activity a VS tervezőfelületén. A designer osztályhoz egy saját theme osztályt fogunk rendelni, ami pedig azt határozza meg, hogy az adott komponens milyen színekkel, betűtípusokkal, betűméretekkel ábrázolódjon.

Ez idáig aránylag egyszerű, mindössze a designer OnPaint metódusát kell felüldefiniálni úgy, hogy az összes stílus paramétert a theme osztályból vesszük. Ezt meg is lehet csinálni és hamar rá fogunk jönni, hogy a WF tervezői valószínűleg azért rajzoltak minimális activity-ket, hogy egyszerre sok elférjen a VS ablakában. Ha túl kicsi, akkor is használhatatlan, ha túl nagy, akkor is.

Olyan megoldás kellene, hogy tudjuk változtatni, mekkora az activity felülete fejlesztés közben. Ezt meg lehet oldani úgy, hogy kezeljük az egér eseményeket a designerben, de meg lehet oldani úgy is, ahogy ún. composite activity designert készítünk. A composite activity olyan komponens, aminek gyerekei lehetnek, tehát például az IfElse activitynek a lehetséges kimenetei (branchek) a gyermekei. Az ilyen activity-k elég összetettek lehetnek ahhoz, hogy be lehessen csukni és ki lehessen nyitni őket a dizájnerben, aminek a támogatására létezik egy CompositeActivityDesigner ősosztály, amiből mi származtathatunk.

Készítsünk tehát olyan composite activity designert, amit ki lehet nyitni és be lehet csukni fejlesztés közben!

Saját composite activity designer készítése

Kezdjük a témával, abból is összetett kell, származtassunk egyet a CompositeDesignerTheme osztályból és színezzük ki kedvünk szerint:

    public class DemoDesignerTheme : CompositeDesignerTheme
    {
        public DemoDesignerTheme( WorkflowTheme theme )
            : base( theme )
        {
            this.BorderColor = Color.Brown;
            this.BackColorStart = Color.LightYellow;
            this.BackColorEnd = Color.Orange;
            this.BackgroundStyle = LinearGradientMode.Vertical;
            this.ForeColor = Color.Brown;
        }
    }

Ezek után már létrehozhatjuk a designer osztályunkat és hozzácsaphatjuk a témát is. Nagy buzgalommal definiáljuk felül az Initialize metódust, hogy el tudjuk menteni a megrajzolandó activity-re mutató referenciát (erre majd később szükség lesz):

    [ActivityDesignerTheme( typeof( DemoDesignerTheme ) )]
    public class DemoDesigner : CompositeActivityDesigner
    {
        private Activity _activity;

        protected override void Initialize( Activity activity )
        {
            this._activity = activity;
            base.Initialize( activity );
        }
    }

Következő lépésben definiáljuk felül az OnPaint metódust és bányásszuk ki az értelmes dolgokat az esemény paraméterből:

    protected override void OnPaint( ActivityDesignerPaintEventArgs e )
    {
        Graphics g = e.Graphics;
        CompositeDesignerTheme theme = e.DesignerTheme as CompositeDesignerTheme;

        // Tovább is lesz még...
    }

Ott az a csodás Graphics objektum, azon kell kiélnünk rajz tehetségünket. Mindenek előtt talán rajzoljuk meg az activity keretét, még pedig olyan pompás lekerekített formában, ahogy a standard beépített dizájnerek teszik. A bátrabbak megrajzolják a keretet ívekből, a naívabbak még hisznek az MSDN-ben, a gyakorlottabbak pedig Reflectoroznak, és így rátalálnak az ActivityDesignerPaint osztályra. Ennek az osztálynak van néhány publikus metódusa, amelyek közvetlenül használhatóak, de az internalokból is lehet ötleteket meríteni:

    // Keret megrajzolása
    int radius = 4;
    ActivityDesignerPaint.DrawRoundedRectangle( g, theme.BorderPen, this.Bounds, radius - 2 );

Tartsuk fejben, mert a Google-ben mindössze 5 találat van rá! (Talán ezért írta meg kézzel az, aki a Microsoft oldalán lévő WF hands-on labot kitalálta, bár ez sajnos még a kisebb hiba abban a példakódban… smile_confused)

Fessük ki a keretet, de ne azzal a színnel, ami eszünkbe jut, hanem használjuk a téma beállításait:

    // Háttér kifestése
    GraphicsPath path = ActivityDesignerPaint.GetRoundedRectanglePath( this.Bounds, radius );
    g.FillPath( theme.GetBackgroundBrush( this.Bounds ), path );

Mivel az egész OnPaintet felülírjuk, mindenről nekünk kell gondoskodni, így az ikon megjelenítéséről is:

    // Ikon megjelenítése
    ActivityDesignerPaint.DrawImage( g, this.Image, this.ImageRectangle, DesignerContentAlignment.Fill );

És a szöveg kiírásáról is:

    // Szöveg megjelenítése
    ActivityDesignerPaint.DrawText( g, theme.Font, this.Text, this.TextRectangle, 
StringAlignment.Near, e.AmbientTheme.TextQuality, theme.ForegroundBrush );

Itt jön a trükk: rajzoljuk meg a nyitogató gombot, de ezt is bízzuk a profira:

    // Kinyitó ikon megjelenítése
    ActivityDesignerPaint.DrawExpandButton( g, this.ExpandButtonRectangle, !this.Expanded, theme );

Ha idáig eljutottunk, akkor már van egy szép színes, nyomkodható activity-nk, sőt még a jobb egérkettyintős menüben is megjelent az Expand és Collapse parancs:

Saját composite activity

Az activity méretét nyilvánvalóan meg kell változtatnunk, amikor a felhasználó ki szeretné nyitni. Ehhez nem kell egérkattintás eseményt kezelnünk, a VS gondoskodni fog arról, hogy a kattintás után újrarajzolja a teljes activity-t, csak éppen az Expanded tulajdonság értéke fog mást mutatni.

Tűzzük ki célul azt, hogy kinyitott állapotban megjelenítsük az activity Description mezőjének az értékét is, az activity pedig legyen olyan széles, hogy a teljes szöveg tördelés nélkül beleférjen. A méretet az OnLayoutSize metódus felüldefiniálásával tudjuk megadni:

    protected override Size OnLayoutSize( ActivityDesignerLayoutEventArgs e )
    {
        // Meg kell hívni, mert ez inicialize1lja a TextRectangle-t, 
        // amitől az ImageRectangle és az ExpandButtonRectangle is függ
        Size originalSize = base.OnLayoutSize( e );

        string text;
        int height;

        if( this.Expanded )
        {
            // Kinyitott állapotban a Description mérete a mérvadó
            text = this._activity.Description;
            height = originalSize.Height + 30;
        }
        else
        {
            // Becsukott állapotban az activity azonosítójának mérete a mérvadó
            text = this.Text;
            height = originalSize.Height;
        }

        // Az activity mérete a szöveg szélesslgéhez igazodik.
        SizeF s = e.Graphics.MeasureString( text, e.DesignerTheme.Font );
        return new Size( (int) s.Width + 30, height );
    }

A fenti metódusnak van két érdekessége (a MeasureString metóduson kívül persze):

  • Az ikon és a szöveg pozícionálásánál hivatkoztunk az ImageRectangle és a TextRectangle tulajdonságokra, sőt később az ExpandButtonRectangle-re is. Ezeket is felül lehet definiálni, de nem szükséges, mert az activity méretében származtatják magukat, de csak akkor tudják, ha meghívjuk a szülő osztály OnLayoutSize metódusát.
  • Ki lehet próbálni, hogy bármilyen rövid szövegeket adunk meg, az activity nem csökken akármilyen kicsire. Ezt a MinimumSize tulajdonság határozza meg, amit szintén felül lehet definiálni.

Nem maradt más hátra, mint hogy az OnPaintben kinyitott állapotban az ikon alá kiírjuk az activity-hez tartozó Description tulajdonság értékét:

    // Kinyitott állapotban a Description megjelenítése
    if( this.Expanded )
    {
        Rectangle rect = new Rectangle();
        rect.X = this.Bounds.X;
        rect.Y = this.ImageRectangle.Y + this.ImageRectangle.Height + 10;
        rect.Width = this.Bounds.Width;
        rect.Height = this.TextRectangle.Height;

        ActivityDesignerPaint.DrawText( g, theme.Font, this._activity.Description, rect, 
StringAlignment.Center, e.AmbientTheme.TextQuality, theme.ForegroundBrush ); }

Ennél természetesen tovább is lehet menni, például reflection segítségével fel lehet deríteni az activity tulajdonságait és a hozzájuk tartozó attribútumokat és meg lehet jeleníteni azokat is a tervezőben, a nyitott nézetben. Ha kell fejlesztés közben, akkor egy kattintással kinyithatjuk, sőt ki is nyomtathatjuk. Íme tehát a végeredmény összecsukva és kinyitva:

Saját activity összecsukva Saját activity kinyitva

Többekkel beszélgettem már arról, hogy a Windows Workflow Foundation mennyire számít rapid alkalmazásfejlesztési technológiának, azt hiszem ez egy újabb példa arra, hogy nem az.

Az activity teljes forráskódja a devPORTALról tölthető le.

 

Technorati tags: , ,