in

dotNet Umbria

Il primo User Group in Umbria sul mondo .Net

Paolo Possanzini

December 2007 - Posts

  • Utilizzare Trigger DDL per tenere allineati i database remoti

    In alcune applicazioni è spesso necessario creare database locali che si sincronizzano in qualche modo con il database presente su un server. Esempio tipico di applicazioni di questo tipo è Outlook, dove è necessario avere una copia dei dati locali in modo da poter lavorare in un ambiente parzialmente connesso. In scenari di questo tipo, specialmente nella fase di sviluppo e test dell'applicazione, ci può essere l'esigenza di modificare il database, e quindi di replicare tali modifiche a tutti i client insieme all'aggiornamento delle procedure di accesso ai dati. Tenere traccia delle modifiche effettuate e creare procedure di allineamento delle strutture, senza creare problemi ai dati presenti nei db remoti, è a volte una operazione lunga e che richiede parecchi test. I Trigger DDL ci vengono sicuramente in aiuto in scenari di questo tipo.

    Un Trigger DDL è un particolare tipo di trigger di SQL Server 2005 in grado di intercettare tutte le operazioni DDL (Data Definition Language) e che quindi modificano la struttura della base dati.
    Un buon esempio di un trigger di questo tipo è presente all'interno del database AdventureWorks. In pratica ogni operazione di Create, Alter, Drop, etc. di qualsiasi struttura del DB può essere intercettata e memorizzata in un'apposita tabella.

    Durante il deployment delle nostre applicazioni, potremo integrare il setup con una routine che riesegue sul DB client tutte le query DDL effettuate sul server in modo da rendere le strutture dei due DB assolutamente uguali.
    Ecco come avviene la creazione di un trigger DDL

     

    [code language="sql"]

    CREATE TRIGGER myDDLTrigger ON DATABASE
    FOR DDL_DATABASE_LEVEL_EVENTS AS
    BEGIN
        SET NOCOUNT ON;

    END

    [/code]

     

    La clausola FOR DDL_DATABASE_LEVEL_EVENTS  indica che è richiesta l'intercettazione di TUTTI gli eventi DDL che si verificano all'interno del database in cui il trigger si trova.
    Possiamo sostituire questa clausola con l'elenco degli eventi che intendiamo intercettare. Per avere una idea del tipo di eventi che possono essere intercettati con questo tipo di trigger è sufficiente eseguire questa query all'interno di un Database di  SQL Server 2005

     

    [code language="sql"]


    select type_desc from sys.trigger_events WHERE type >20

    [/code]

     

    Una volta intercettato l'evento all'interno del trigger otteniamo una struttura XML che descrive esattamente il tipo di operazione che è stata effettuata, con tanto di query eseguita per effettuarla.
    Possiamo salvare il dato in formato xml oppure navigare nel documento con XQuery ed esaminarne il contenuto.

    [code language="sql"]

    CREATE TRIGGER myDDLTrigger ON DATABASE
    FOR DDL_DATABASE_LEVEL_EVENTS AS
    BEGIN
        SET NOCOUNT ON;

        DECLARE @data XML;
        SET @data = EVENTDATA();  -- La variabile @data contiene la struttura xml con il dettaglio delle modifiche effettuate.

    END

    [/code]

    A questo punto possiamo creare una tabellina in cui memorizzare i valori ottenuti.

    [code language="sql"]

    CREATE TABLE myDbLog
    (
      Id  uniqueidentifier,
      operationdate datetime,
      operation xml
    ) ON [Primary]
    GO

    CREATE TRIGGER myDDLTrigger ON DATABASE
    FOR DDL_DATABASE_LEVEL_EVENTS AS
    BEGIN
        SET NOCOUNT ON;

        DECLARE @data XML;
        SET @data = EVENTDATA();  -- La variabile @data contiene la struttura xml con il dettaglio delle modifiche effettuate.

        INSERT INTO myDbLog
        VALUES (newid(), getdate(), @data)

    END
    GO

    [/code]


    Ovviamente possiamo rendere più ricca la nostra tabella esponendo già come campi, i dati presenti all'interno della struttura xml.

  • Controllo per la visualizzazioni di Grafici 3D in WPF. (Preparazione dell'usercontrol)

    Il nostro controllo per la visualizazione di grafici 3D, dovra essere inserito dentro il ViewPort3D, quindi dovrà ereditare ModelVisual3D


    [code language="c#"]

    /// Autore: Paolo Possanzini
    /// WebSite: http://www.teamdev.it
    /// email: paolo@teamdev.it
    public class WpfChart : ModelVisual3D, ISupportInitialize
    {

    ....

    }

    [/code]

     

    Da notare che il nostro controllo implementerà anche ISupportInitialize, questo ci permette di capire quando stato inizializzato oppure quando è in fase di inizializzazione.
    A questo punto possiamo iniziare ad inserire all'interno del nostro controllo. I grafici saranno visualizzati a partire da una sorgente dati, quindi mettiamo a disposizione dello sviluppatore una proprietà per agganciare la sorgente dati al nostro controllo.

    [code language="c#"]

    /// Autore: Paolo Possanzini
    /// WebSite: http://www.teamdev.it
    /// email: paolo@teamdev.it
    public class WpfChart : ModelVisual3D, ISupportInitialize
    {


    private static DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(WpfChart));
    private static DependencyProperty ItemTemplateProperty = DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(WpfChart));

    public IEnumerable ItemsSource
    {
      get { return base.GetValue(ItemsSourceProperty) as IEnumerable; }
      set
      {
        if (value == null)
          base.ClearValue(ItemsSourceProperty);
        else
          base.SetValue(ItemsSourceProperty, value);
        RefreshBars();
      }
    }

    ....

    }

    [/code]

    Ci servono anche altre proprietà che implementeremo in modo analogo, le proprietà che ci servono sono : ItemTemplate, Transform, ItemTemplateName.
    ItemTemplate ed ItemTemplateName ci servono per implementare una struttura simile agli ItemTemplate presenti nelle ListView.

    A questo punto siamo pronti per iniziare a preoccuparci di cosa visualizzare all'interno del nostro controllo.

  • Ottenere l'icona di default di un tipo di file.

    Spesso capita di dover creare una struttura per allegare alcuni file all'interno delle nostre applicazioni
    Ecco un piccolissimo frammento di codice che aiuta ad ottenere a runtime l'icona di default per ogni tipo di file conosciuto dalla nostra macchina.

    [code language="c#"]

    [DllImport("Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons);

    public static Icon GetIconForFileExtension(string fileextension)
    {
      try
      {
        // Verifico la struttura dell'estensione (deve avere il puntino)
        if (!fileextension.StartsWith("."))
          fileextension = "." + fileextension;

        // Apro la chiave di registro dell'estensione ed ottengo l'applicazione associata al tipo di file
        RegistryKey fileextregkey = Registry.ClassesRoot.OpenSubKey(fileextension);
        string applicationname = fileextregkey.GetValue(string.Empty).ToString();

        // Apro la chiave di registro dell'applicazione ed ottengo il path e la posizione dell'icona di default.
        RegistryKey defaulticonkey = Registry.ClassesRoot.OpenSubKey(applicationname + @"\DefaultIcon");
        string defaulticonpath = defaulticonkey.GetValue(string.Empty).ToString();

        // Il tipo di file è composto da due parti separate da virgola, quindi procedo con lo split.
        string[] iconargs = defaulticonpath.Split(',');

        IntPtr large, small;

        // Eseguo la chiamata alla API che mi permette di estrarre gli Handle che contengono le mie icone.
        ExtractIconEx(iconargs[0], int.Parse(iconargs[1]), out large, out small, 1);
        // Ottengo l'icona dall'Handle
        Icon extractedIcon = Icon.FromHandle(small);
        return extractedIcon;
      }
      catch
      {
        return null;
      }
    }

    [/code]

  • Estrarre i valori di default per una custom entity da SQL Server 2005.

    Oggi mi è capitato di dover generare un po' di codice per assegnare a delle custom entity i valori di default presenti all'interno della definizione delle colonne di un database SQL.

    [code language='SQL']

    DECLARE @entityname varchar(50)
    DECLARE @tablename varchar(50)
    DECLARE @columnfilter varchar(50)

    SET @entityname = 'myobjectname'
    SET @tablename = 'mytable'
    SET @columnfilter  = ''

    Select    @entityname + '.' + sys.columns.name + ' = ' +
            REPLACE(
                REPLACE(
                    REPLACE(sys.default_constraints.definition,'(','')
                ,')','')
            ,'''','"')
            + ';'
            FROM sys.columns
            JOIN sys.tables ON
                sys.columns.object_id = sys.tables.object_id
            JOIN sys.default_constraints ON
                sys.columns.default_object_id = sys.default_constraints.object_id

                WHERE        sys.tables.name        = @tablename   
                        AND    sys.columns.name    Like(@columnfilter + '%')

    [/code]

    Ecco la query che ho utilizzato per generare il codice C# direttamente da SQL Server

  • Spread dotnetumbria.org

    Scrivo questo post perchè voglio mettere un po' in risalto una bella iniziativa che è nata in questo post : Spread dotnetumbria.org
    Diamo una mano alla diffusione dello user group inserendo un link a dotnetumbria nei nostri siti.
    Oppure caricate un vostro logo di dotnetumbria sul forum. Smile Un ringraziamento particolare a pomarc per questa bella idea.

    dotnetumbriajoinus

  • Controllo per la visualizzazione di Grafici 3D in WPF. (Preparazione dell'ambiente 3D)

    Mi ha sempre affascinato l'idea di creare in modo abbastanza semplice oggetti 3D con WPF. La cosa che mi è sempre servita è un controllo per la visualizzazione di grafici a barre o simili.
    Vediamo come crearne uno in WPF.

    Per prima cosa ci serve conoscere alcune nozioni base della visualizzazione di oggetti 3D in WPF.

    1) Tutto quello che deve essere visualizzato con una rappresentazione 3D dei dati deve essere inserito all'interno di un Viewport3D. Immaginatelo come un contenitore di oggetti che vivono in un mondo 3D.
    2) Occorre definire alcune luci per "illuminare" i nostri oggetti
    3) Occorre definire una telecamera per "riprendere" i nostri oggetti e visualizzarli sul nostro monitor. Saremo così come di registi sulla scena di un film.
    Non entrerò nel dettaglio di come creare una scena 3D perchè Andrea nei suoi prossimi post spiegherà bene come è strutturato un ambiente 3D in WPF.
    Nel nostro caso gli esempi dovrebbero bastare. ( Se non bastassero chiedete pure )

    Definiamo tutto questo

    [code language="xml"]

    <Viewport3D Name="mainViewport" ClipToBounds="True">
        <Viewport3D.Camera>
            <PerspectiveCamera
              FarPlaneDistance="150"
              LookDirection="-10,-6,-10"
              UpDirection="0,3,0"
              NearPlaneDistance="1"
              Position="20,20,20"
              FieldOfView="70" />
        </Viewport3D.Camera>
    ....
    </Viewport3D>

    [/code]

    Con il tag <Viewport3D.Camera> definiamo come deve essere posizionata la nostra camera, Con l'attributo position la posizioniamo nel punto x=20, y=20, z=20 e con l'attributo LookDirection gli diciamo che deve essere puntata verso il punto x=-10, y=-6, z=-10. In pratica quarda verso l'origine ma un pochino più in alto dell'origine.

    Definiamo una luce e quindi modifichiamo il nostro codice in questo modo:

    [code language="xml"]

    <Viewport3D Name="mainViewport" ClipToBounds="True">
        <Viewport3D.Camera>
            <PerspectiveCamera
              FarPlaneDistance="150"
              LookDirection="-10,-6,-10"
              UpDirection="0,3,0"
              NearPlaneDistance="1"
              Position="20,20,20"
              FieldOfView="70" />
        </Viewport3D.Camera>
    ....
        <ModelVisual3D>
            <ModelVisual3D.Content>
                <DirectionalLight
                    Color="White"
                    Direction="-5,-5,-10" />
            </ModelVisual3D.Content>
        </ModelVisual3D>
    </Viewport3D>

    [/code]

    Il ModelVisual3D è un oggetto renderizzabile all'interno del mondo 3D, contiene gli oggetti più semplici e definisce come questi debbano comportarsi nei confronti del mondo 3D. Il modelVisual3D permette di applicare agli oggetti 3D alcune traformazioni come traslazioni e rotazioni rispetto all'origine. E' un contenitore di primitive.
    Inseriamo nel Content di questo oggetto la nostra luce.
    Iniziamo ad inserire nel nostro mondo 3D alcune primitive. Tutte le primitive vanno messe all'interno della proprietà ModelVisual3D.Children. Quindi il nostro codice cambierà nella forma seguente:

    [code language="xml"]

    <Viewport3D Name="mainViewport" ClipToBounds="True">
        <Viewport3D.Camera>
            <PerspectiveCamera
              FarPlaneDistance="150"
              LookDirection="-10,-6,-10"
              UpDirection="0,3,0"
              NearPlaneDistance="1"
              Position="20,20,20"
              FieldOfView="70" />
        </Viewport3D.Camera>
        <ModelVisual3D>
            <ModelVisual3D.Children>
            </ModelVisual3D.Children>
            <ModelVisual3D.Content>
                <DirectionalLight
                    Color="White"
                    Direction="-5,-5,-10" />
            </ModelVisual3D.Content>
        </ModelVisual3D>

    </Viewport3D>

    [/code]

    Un'ultima cosa che dobbiamo aggiugere è la posizione del nostro ModelVisual3D rispetto al ViewPort3D.
    Quindi inseriamo alcune trasformate che posizioneranno il nostro oggetto in un punto differente dal punto x=0, y=0, z=0.
    E gia che ci siamo prepariamo il nostro ModelVisual3D ad essere sottoposto ad altre trasformazioni.

    [code language="xml"]

    <Viewport3D Name="mainViewport" ClipToBounds="True">
        <Viewport3D.Camera>
            <PerspectiveCamera
              FarPlaneDistance="150"
              LookDirection="-10,-6,-10"
              UpDirection="0,3,0"
              NearPlaneDistance="1"
              Position="20,20,20"
              FieldOfView="70" />
        </Viewport3D.Camera>

        <ModelVisual3D>
            <ModelVisual3D.Transform>
                <Transform3DGroup>
                    <Transform3DGroup.Children>
                        <Transform3DCollection >

                            <ScaleTransform3D ScaleX="1" ScaleY="1"  ScaleZ="1" />
                            <RotateTransform3D>
                                <RotateTransform3D.Rotation>
                                    <AxisAngleRotation3D Axis="0 1 0" Angle="0" />
                                </RotateTransform3D.Rotation>
                            </RotateTransform3D>
                            <TranslateTransform3D OffsetX="0" OffsetY="0" OffsetZ="0" />

                        </Transform3DCollection>
                    </Transform3DGroup.Children>
                </Transform3DGroup>
            </ModelVisual3D.Transform>
            <ModelVisual3D.Children>

            </ModelVisual3D.Children>

            <ModelVisual3D.Content>
                <DirectionalLight
                    Color="White"
                    Direction="-5,-5,-10" />
            </ModelVisual3D.Content>
        </ModelVisual3D>

    </Viewport3D>

    [/code]

    Il nostro ModelVisual3D è pronto per contenere oggetti di base epuò anche essere posizionato, traslato e ridimensionato a nostro piacimento attraverso le trasformate 3D che abbiamo inserito nell'attributo ModelVisual3D.Transform

    Il nostro mondo virtuale 3D è pronto. il Viewport può essere inserito all'interno di qualunque controllo WPF 2D.

    Chiaramente se ce lo mettiamo adesso non vedremo niente perchè non c'è nulla da renderizzare.

dotNet Umbria 2007-2008
Powered by Community Server (Commercial Edition), by Telligent Systems