Roberto Brunetti

Developing in the cloud

.NET Programming

Archives

February 2008 - Posts

Workflow Foundation: Uno Spettacolo !

Chi ci conosce sa che non facciamo pubblicità a prodotti e tecnologie: spesso cerchiamo di evidenziare quanto sia importante conoscere a fondo una tecnologia prima di utilizzarla. Da qualche anno gli strumenti di sviluppo semplificano sempre di più la vita agli sviluppatori, ma è diventato sempre più difficile mettere insieme i pezzi: le tecnologie sono sempre più legate l'una all'altra ed è impossibile sapere tutto di tutto. I prodotti, lasciati ai loro default, funzionano ad un livello medio: non potrebbe essere diversamente. Spesso ci sono oggetti o componenti che vanno benissimo in certi contesti, ma sono assolutamente inappropriati in altri; tanto per cambiare mi vengono in mente le Session di ASP.NET che utilizzate in contesti molto piccoli non danno nessun tipo di problema e aiutano nello sviluppo, ma portate in applicazioni più serie (voglio anche dire applicazioni in cui occorre sapere cosa c'è nella sessione di ogni utente: ad esempio il carrello della spesa su un sito di eCommerce) sono assolutamente inutilizzabili.

Workflow Foundation rientra in questa categoria di tecnologie: nasce come prodotto per gestire Worfklow (punto). Come tale deve essere impiegato in scenari statefull e stateless, può gestire i processi di Business così come la User Interface. Settimana scorsa ho erogato il nostro corso su WF da un nostro cliente e come è accaduto per tutte le edizioni precedenti, la prima mattina vola via sulle caratteristiche principali; l'impatto sull'audience è notevole e i commenti più blasonati sono "Spettacolo", "Quanto si semplifica lo sviluppo e la manuteniblità", "Utilissimo per dare uno strumento di disegno a chi non scrive codice ma conosce la problematica e lo stesso strumento allo sviluppatore di Activity che eseguire le operazioni fisiche".

Il pomeriggio del primo giorno si riprendono tutti gli argomenti e si comincia a scendere nei dettagli di Hosting e Runtime (senza ancora affrontare i servizi) e la giornata sta per concludersi con l'entusiamo alle stelle visti quanti servizi espone. Si affronta l'argomento asincrono, già perchè Wf lavora in asincrono per default e iniziano i primi dolori :-) Lavorare in asincrono è bello, oltre che efficace.

La mattina seguente si affronta il ManualScheduler che esegue le workflow instance sullo stesso thread del chiamante e la fiducia ritorna ai massimi livelli: ci sono però molte controindicazioni a lavorare in sincrono e il modo con cui si affronta l'hosting in applicazioni server-side (ASP.NET ad esempio) ricomplica anche lo scenario sincrono in quanto per evitare persistenze inutili (e soprattutto pesanti) occorre prestare molta attenzione e scrivendo il codice bene e configurando il runtime e la persistenza nel modo corretto. Tutti i parametri spaventano a prima vista.

Poi si apre lo scenario comunicazioni con l'esterno partendo da Eventi e Metodi di scambio dati con host, che si effettua sempre tramite interfacce, e di seguito si affronta la comunicazione con altri workflow e con servizi ASMX tramite Activity asincrone che si avvalgono di code: a prima vista è una cosa complicata da realizzare e il "terrore" negli occhi dei partecipanti è visibile anche a luce spenta :-) Subito dopo però si evidenziano i benefici di lavorare in questo modo e tutto diventa di nuovo entusiasmante.

Si chiude il tutto (il terzo giorno di solito) con una analisi dei servizi di persistenza, traking, commit e work batch, IPending Work: sui primi la valutazione iniziale è "cacchio", non è esattamente questa l'escalmazione ma ci assomiglia molto soprattutto nelle prime due lettere :-), mentre sugli ultimi due punti ritorna il panico.

Workflow è veramente un gran prodotto: serve solamente una buona preparazione e un po' di pratica; del resto su tutti i prodotti servono questi due ingredienti. Sicuramente si possono fare tanti casini e il prodotto è relativamente nuovo quindi chi non lo approccia nel modo corretto si trova un qualcosa che vive di vita propria; in realtà la configurazione e il corretto utilizzo consentono di fare cose eccellenti.

La nostra prima applicazione su Workflow risale ormai a due anni fa (abbiamo iniziato con la Beta su un progetto reale) e, nonostante le varie prove semplici e lo studio che avevamo alle spalle prima di intraprendere questa strada, Paolo e io abbiamo dovuto spendere un po' di tempo prima di trovare la strada giusta per il tipo di applicazione. A distanza di due anni posso dire che abbiamo preso la strada giusta e alla fine, lo sviluppo, anche nei primi mesi dopo le elucubrazioni di cui sopra, è stato molto più che soddisfacente in termini di produttività e modifiche che abbiamo dovuto fare in corsa causa analisi incompleta. Modificare i flussi da un designer significa risparmiare molto, ma molto tempo, rispetto a dover riprendere in mano centinaia di righe di codice.

Il nostro mondo è bello proprio perchè possiamo lavorare con tecnologie come questa: a mio avviso è il più bel prodotto che sia stato presentato negli ultimi anni e rapprensenta un notevole, per non dire enorme, passo avanti nella scrittura di applicazioni.

Spero di avervi convinto a dare almeno un'occhiata a questa tecnologia.

PS: per chi non ha mai visto questa tecnologia abbiamo pensato ad una sessione di quasi 4 ore alla nostra DevCon 2008 che si terrà a Milano a fine maggio.

Convertire una macchina virtuale VMWare a Virtual PC/Virtual Server

Oggi, da un cliente, ho dovuto convertire un paio di macchine virtuali VMWare a Virtual Server: i server di sviluppo sono stati convertiti a Virtual Server.

Non esistendo un tool nativo di importazione della macchina virtuale abbiamo deciso di usare l'utility VMDK to VHD Converter disponibile nella sezione Download di http://vmtoolkit.com/files/default.aspx.

Lo strumento converte semplicemente il disco VMDK in VHD consentendo poi la creazione della macchina Virtual PC o Virtual Server agganciando un disco esistente.

La conversione dell'hard disk deve però essere effettuata dopo qualche modifica manuale.

Riporto tutti i passi seguiti oggi evitando di linkare post esterni visto che negli ultimi tempi sembra che la moda porti i webmaster a spostare le cose senza mettere redirezioni :-)

0) Copiare la Virtual Machine o eseguire un Clone per lasciare intatta la macchina originale 

1) Disinstallare i VMWare Tools. Al termine Reboot

2) Se durante il reboot viene fuori il wizard di Add/Remove Hardware annullare l'operazione

3) Verificare la versione del Service Pack. Se non ci sono SP installati prendere il CD originale o tenere a portata di mano la directory i386. Se ci sono SP installati occorrono i file di setup del Service Pack accessibil: se avete il SP installato con i file copiati in x:\windows\servicepackfiles è sufficiente copiare i file indicati senza bisogno del CD originale

4) Aprire il Command Prompt

5) Se avete il SP nella directory servicepackfiles copiare hal.dll sotto x:\windows\system32\

6) Se non avete il SP nella directory servicepack file occorre la directory i386 a portata di mano e lanciare expand d:\\i386\\hal.dl_ %windir%\\system32\\hal.dll

7) Eseguire la stessa operazione (5 o 6) per ntoskrnl.exe (copia del file oppure expand d:\\i386\\ntoskrnl.ex_ %windir%\\system32\\ntoskrnl.exe)

In ultimo, prima di lanciare l'utility di esportazione del VMDK copiare nella macchina virtuale il seguente script e lanciarlo. Al termine dello script la macchina esegue uno shut down ed è pronta per l'esportazione dal tool citato all'inizio del post. 

Create un file .vbs (per Windows Scripting Host) e lanciarlo. Se al termine dello script (dopo la MessageBox) il sistema non si riavvia, riavviarlo a mano: probabilmente l'impersonation non riesce e quindi non ci sono i diritti per fare shutdown.

 'prepvm.vbs
'Removes VMware-specific drivers from a system
On Error Resume Next

' Instantiate Shell Object
Set objShell = CreateObject("WScript.Shell")

' Disable VMware Tools Service
objShell.RegWrite "HKLM\\SYSTEM\\CurrentControlSet\\Services\\VMTools\\Start", _
                 4, "REG_DWORD"

' Disable VMware vmx_svga video driver
objShell.RegWrite "HKLM\\SYSTEM\\CurrentControlSet\\Services\\vmx_svga\\Start", _
                 4, "REG_DWORD"

' Disable VMware vmmouse driver
objShell.RegWrite "HKLM\\SYSTEM\\CurrentControlSet\\Services\\vmmouse\\Start", _
                 4, "REG_DWORD"

' Disable VMware vmscsi driver
objShell.RegWrite "HKLM\\SYSTEM\\CurrentControlSet\\Services\\vmscsi\\Start", _
                 4, "REG_DWORD"
             
' Disable VMware PCnet driver
objShell.RegWrite "HKLM\\SYSTEM\\CurrentControlSet\\Services\\PCnet\\Start", _
                 4, "REG_DWORD"

' Disable VMware Buslogic driver
objShell.RegWrite "HKLM\\SYSTEM\\CurrentControlSet\\Services\\buslogic\\Start", _
                 4, "REG_DWORD"

' Disable SCSI Miniport drivers
objShell.RegWrite "HKLM\\SYSTEM\\CurrentControlSet\\Services\\symc810\\Start", _
                 4, "REG_DWORD"
objShell.RegWrite "HKLM\\SYSTEM\\CurrentControlSet\\Services\\symc8xx\\Start", _
                 4, "REG_DWORD"
objShell.RegWrite "HKLM\\SYSTEM\\CurrentControlSet\\Services\\cpqarray\\Start", _
                 4, "REG_DWORD"
objShell.RegWrite "HKLM\\SYSTEM\\CurrentControlSet\\Services\\pcntn4m\\Start", _
                 4, "REG_DWORD"
objShell.RegWrite "HKLM\\SYSTEM\\CurrentControlSet\\Services\\cpqnf3\\Start", _
                 4, "REG_DWORD"
objShell.RegWrite "HKLM\\SYSTEM\\CurrentControlSet\\Services\\MRaidNT\\Start", _
                 4, "REG_DWORD"

' Restart Computer
strComputer = "."

'Prompt user of impending reboot
WScript.Echo("The system is prepared for imaging and will now shutdown.")
WScript.Sleep(3)
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate,(Shutdown)}!\\\\" & _
        strComputer & "\\root\\cimv2")

Set colOperatingSystems = objWMIService.ExecQuery _
    ("Select * from Win32_OperatingSystem")

For Each objOperatingSystem in colOperatingSystems
    objOperatingSystem.Shutdown()
Next

 

ADO.NET Synchronization Services: Considerazioni

.NET 3.5 porta con sè un componente non troppo pubblicizzato denominato ADO.NET Synchronization Framework. L'idea fa parte di un ben più allargato Microsoft Synchronization Framework che vedrà la luce prossimamente come framework comune per la sincronizzazione di informazioni.

In questo post volevo sottolineare alcuni aspetti su cui si trovano informazioni contrastanti.

Gli oggetti supportati dal motore di sincronizzazione sono:

1) Table per tutte le tipologie di sincronizzazione

2) View per sincronizzazioni Snapshot e Download-Only

3) Il client appoggia i dati su SQL CE 3.5 e NON su SQL Express (almeno nella versione attuale)

4) Per default non vengono portati sul db locale i constraint di FOREIGN KEY, DEFAULT e UNIQUE.
    Se occorre abilitare (e spesso è giustamente necessario) questi constraint lato client occorre modificare lo schema del DB sul client.
    Questa operazione può essere effettuata utilizzando comandi DDL dopo la prima sincronizzazione dei dati, ma è consigliabile utilizzare l'oggetto SyncSchema.
    In ogni caso è poi possibile modificare lo schema del DB lato client.
    Se gli schemi sono diversi tenere in considerazione questa semplice regola:
        Se viene replicato un campo (ovvero fa parte della SELECT di scaricamento dei dati) che non esiste sul client, il campo viene ignorato
        Se il client ha un campo in più rispetto a quanto viene sincronizzato il campo verrà valorizzato con il suo DEFAULT se presente o con NULL.

5) Le colonne con proprietà ROWGUIDCOL vengono invece portare su SQLCE, ma senza la proprietà ROWGUIDCOL

6) Il client appoggia i dati su tabelle anche se viene sincronizzata una View...ovviamente

7) Non sono supportati gli oggetti fully-qualified: in pratica se abbiamo una tabella EstatesManagement.tabSalesman dove EstatesManagement rappresenta l'owner o lo schema. Occorre usare solo il nome della tabella.

8) Il framework fa parte di .NET 3.5 e non del .NET CF 3.5, quindi questo motore di sincronizzazione dei dati NON è utilizzabile (almeno nella versione attuale) da dispositivi Windows Mobile.

Si possono lanciare una sincronizzazione alla volta: anche eseguendo la sincronizzazione da un thread separati non è possibile lanciare sincronizzazioni contemporanee sugli stessi oggetti: in pratica se una tabella è oggetto di una replica in corso, non è possibile lanciare un'altra sincronizzazione in parallelo che utilizzi la stessa tabella.

Non è supportata la gestione dei campi Identity: in pratica il motore di sincronizzazione non ha meccanismi nativi per distribuire range di identity ai vari client.

Particolare attenzione deve essere posta nelle procedure di recovery a fronte di un restore dei DB: se il database server viene ripristinato da un restore le modifiche successive potrebbero non venir propagate ai vari client; il motivo è semplice: i client memorizzano solo nel database locale il valore di anchor ottenuto dall'ultima sincronizzaione: se un client era arrivato nella sincronizzazione precedente a recuperare le modifiche, dopo un restore sul server il client continua a chiedere le modifiche effettuate sul server successive all'ultima anchor . Quindi alcune modifiche effettuare sul server dopo il restore non vengono propagate al client in quanto l'anchor sul server ripristinato è inferiore all'anchor memorizzato sul client. Inoltre il client che ha effettuato l'upload di modifiche, dopo un restore del database server, si ritrova delle righe che sul server non esistono (visto che il DB è tornato ad una situazione precedente), e, ancora una volta il client pensa di averle sincronizzate visto che la sincronizzazione precedente era andata a buon fine.

Occorre quindi modificare il comportamento di default del motore di replica. Potremmo prendere spunto al processo utilizzato dalla Merge Replication di SQL Server: memorizzando anche sul server in una nostra tabella le anchor relative ai vari client. Durante ogni sincronizzazione, tramite una modifiche ai vari statement di select delle modifiche occorre incrociare l'anchor arrivata dal client con l'anchor presente sul server e utilizzare il valore minore per selezionare i record oggetto di modifica.

Come ultimo punto, nelle repliche partizionate per singolo utente conviene indicare sempre il parametro ClientId che solitamente si memorizza in un file di configurazione: non specificando questa proprietà il ClientSyncProvider valorizza questa proprietà in base alla chiave di registry HKCU\Software\Microsoft\Microsoft SQL Server Compact Edition\v3.5. Come sappiamo è bene non accedere al registry visto che sono richiesti permessi amministrativi per l'accesso.

Torneremo sull'argomento in altri post e in una sessione dedicata alla nostra DevCon 2008.

Posted: Feb 15 2008, 11:52 AM by rob | with no comments |
DevLeap al lancio di Visual Studio 2008

Come saprete il 28 e 29 febbraio Microsoft Italia ha organizzato il lancio ufficiale italiano di Visual Studio 2008, Windows Server 2008 e SQL Server 2008.

Queste due giornate su Milano avranno il loro seguito con un tour in 6 città italiane.

DevLeap terrà alcune sessioni sia alle giornate di Milano sia durante il tour itinerante. In particolare

  • Marco e Paolo, autori del libro IntroducingLinq e attualmente impegnati nella redazione di un secondo libro su LINQ, terranno la sessione su LINQ all'evento di Milano
  • Luca terrà la sessione su WPF in vari appuntamenti
  • Io invece terrò la sessione su Application Lifecycle Management con Visual Studio Team System in vari appuntamenti

Il sito ufficiale dell'evento è http://www.microsoft.com/italy/launch2008/evento/default.mspx, mentre il blog di MSDN Italia dove trovare altre informazioni sull'evento nonchè articoli e post tecnici è http://blogs.msdn.com/italy

Il calendario del tour è visibile all'indirizzo http://www.microsoft.com/italy/launch2008/roadshow/default.mspx.