Articoli DevLeap

Articoli DevLeap
ADO.NET Synchronization services

Articolo Intro to ADO.NET Sync Services pubblicato su Computer Programming di Marzo 2008.
Autore: Roberto Brunetti

Con l’uscita del Framework .NET 3.5 Microsoft propone il primo tassello di un nuovo framework di sincronizzazione informazioni. Questo primo assaggio, denominato ADO.NET Synchronization Services, semplifica la scrittura di codice per replicare/sincronizzare strutture e dati di un database SQL Server verso client remoti che necessitano di lavorare offline.

L’esigenza di replicare il database o porzioni di esso nasce con l’avvento dei portatili e dei palmari a metà degli anni 90: si pensi al classico scenario di raccolta ordini sul campo in cui il venditore scarica sul suo pc/palmare il listino prodotti (tabelle in solo download), inserisce gli ordini su un database locale (in tabelle di solo upload) e magari può modificare alcune informazioni della tabella clienti preventivamente scaricata e successivamente sincronizzata con il database centrale.

Le prime implementazioni su palmare si sono appoggiate ai meccanismi di replica nativi di SQL CE che, sin dalla sua prima versione, propone due tecniche di replica dei dati: Remote Data Access (RDA) e Merge Replication. La prima tecnica consente allo sviluppatore di indicare la query da eseguire server-side e la tabella in locale in cui accogliere i dati tramite il metodo Pull. Una volta scaricati i dati SQL CE tiene monitorate le modifiche effettuate ai dai in locale e consente con un semplice metodo (Push) di inviare al server solo tali modifiche. Tutte le operazioni vengono avviate da codice e non è necessario ne modificare la struttura ne configurare in modo particolare il database server. Diametralmente opposta come approccio troviamo la seconda tecnica nativa di sincronizzazione dei dati presente sia in SQL CE 2.0 che in SQL Server 2000: la Merge Replication richiede una configurazione del database server che comprende la pubblicazione degli oggetti database da replicare con i client, le modalità di replica, l’assegnazione di range per i campi identity, la definizione dei profili di replica (ad esempio il tipo di compressione o il numero di modifiche da inviare in singoli chunk transazionali al client).

Occupandomi di sviluppo mobile dal 1997 ho lavorato molto sia con RDA, scelta preferita nelle casistiche più semplici, sia con la Merge Replication per scenari più “corposi”. Le innumerevoli possibilità di configurazione della Merge Replication la rendono adatta a tutti gli scenari possibili a patto di avere SQL Server (dalla 2000 in poi) come database server e un server IIS che faccia da tramite http per le richieste che arrivano dal client.

In pratica la Merge Replication

· E’ una tecnologia focalizzata sulla configurazione del server

· E’ una tecnologia che fornisce soluzioni end-to-end

· Non è developer-oriented: il codice lato client indica solamente i parametri da usare per quel particolare tipo di client e connessione

· E’ orientata allo scambio di dati e non all’utilizzo di servizi

Per questi motivi il framework .NET in versione 3.5 propone ADO.NET Sync Services, meccanismo più leggero e più gestibile da codice rispetto alla Merge Replication che meglio si adatta a scenari semplici in cui lo sviluppatore, con un impatto minimo sulla struttura delle tabelle, può controllare la replica dei dati. In pratica questa tecnologia consente di avere una cache locale dei dati sul client e i metodi per poter sincronizzare lo store locale con il database server.

I punti fondamentali da chiarire subito sono i seguenti

· La tecnologia si basa su ADO.NET e quindi può lavorare con varie tipologie di database server side

· Lato client viene usato SQL CE 3.5 come store delle informazioni

· Visual Studio 2008 espone wizard e designer per semplificare lo sviluppo

· Il deployment può essere effettuato con ClickOnce

· L’impatto sul server è minimo

· Nativamente lavora single-tier in client-server oppure multi-tier in client-server

· Non è incluso in questa prima versione il supporto nel .NET Compact Framework 3.5

· Il tutto è estendibile per lavorare via servizi ASMX o WCF

Iniziamo con lo schema architetturale delle varie componenti.

Lato client troviamo le classi denominate Client Synchroniztion Provider che si appoggiano al Synchronization Agent per la sincronizzazione delle informazioni. Il Sync Agent controlla la definizione e la modalità di sincronizzazione delle singole tabelle (Sync Table). Al lancio della sincronizzazione il Sync Agent contatta la parte server (per default in-process nella classica topologia client-server) la quale lancia le query sul database per recuperare i dati modificati dall’ultima sincronizzazione e modificare i dati inviati dal client.

clip_image002

Come si può notare dalla slide del nostro corso vengono utilizzati 3 assembly .NET in forma di dll

· Microsoft.Synchronization.Data.SqlServerCe.dll: è la dll utilizzata lato client per iniziare la fase di sincronizzazione. Le classi che si utilizzano derivano dalle classi base definite in questa dll. La versione di tale dll è 3.5, allineata appunto con SQL CE 3.5 che, come abbiamo accennato, viene utilizzato per lo store lato client.

· Microsoft.Synchronization.Data.dll: è in versione 1.0 e rappresenta la parte client del meccanismo di sincronizzazione dei dati. Ogni tabella da sincronizzare espone, sempre tramite derivazione da una classe base definita in questa dll, il tipo di replica da effettuare (ad esempio la tabella è in solo download piuttosto che in upload/download incrementale).

· Microsoft.Synchronization.Data.Server.dll: sempre in versione 1.0 rappresenta la parte server che viene invocata dalla parte client durante ogni processo di sincronizzazione dei dati: anche in questo caso lo sviluppatore deve creare classi derivate da classi base esposte da questa dll per definire i comandi da lanciare sul database server per recuperare i dati o aggiornare le modifiche effettuate dal client.

In pratica, lo sviluppatore deve quindi aderire a questo modello architetturale, creando semplicemente delle classi derivate che rappresentano le tabelle da replicare e i comandi da lanciare sul database. Tutte le dll fanno parte del Framework .NET versione 3.5 e quindi non richiedono installazioni separate. Questa tecnologia non è utilizzabile con il .NET Compact Framework e quindi esclude di fatto l’utilizzo su device basati su Windows CE (e ovviamente Windows Mobile visto che il sistema operativo è sempre Windows CE).

Per facilitare questo compito allo sviluppatore Visual Studio 2008 espone un nuovo item da inserire in progetti desktop per automatizzare la crezione di queste classi: il nuovo item prende il nome di Local Database Cache ed è utilizzabile in qualunque progetto desktop.

Procediamo con il wizard di Visual Studio 2008 per capire le tipologie di replica possibili, gli impatti sul server e il codice generato lato client.

Aggiungiamo un nuovo item al progetto:

clip_image004

Una volta aggiunto il file .sync è possibile aprirlo con un nuovo editor che facilita la configurazione e la creazione delle classi derivate che abbiamo accennato. La prima parte del designer consente di specificare la stringa di connessione verso il database server e verso il database client SQLCE.

clip_image006

Una volta scelte le connessioni viene creato, se non esistente, il file .SDF di SQLCE all’interno del progetto. Nella parte advanced è possibile scegliere in quali progetti della solution corrente dovranno essere create le classi per la sincronizzazione e se tutte le tabella devono essere sincronizzate in un unica transazione. Queste impostazioni si riflettono sulle proprietà delle classi che Visual Studio crea nei progetti indicati: sono quindi impostazioni modificabili in seguito riaprendo il file .sync oppure modificandoli da codice.

Per ogni tabella (nel nostro caso abbiamo solo la tabella tabFeedback) occorre indicareil tipo di sincronizzazione e se presenti i campi che consentono di individuare le modifiche da scaricare sul client ad ogni replica. Il tutto si effettua semplicemente scegliendo la tabella dal designer:

clip_image008

La prima operazione da eseguire è scegliere la modalità di replica: nella sezione client configuration si puà scegliere se creare una nuova tabella o utilizzare una tabella esistente nel database SQLCE per accogliere i dati che arrivano dal server. Nella prima combo-box invece si indica il tipo di replica da effettuare. Le opzioni sono le seguenti

· Snapshot: ogni operazioni di sincronizzazione sulla tabella scarica l’intero set dei dati

· Download-only: la tabella viene solamente sincronizzata dal server verso il client; vengono scaricate solo le modifiche effettuate dall’utlima sincronizzazione

· Upload-only: la tabella viene solamente sincronizzata dal client verso il server; vengono inviate solo le modifiche effettuate dall’utlima sincronizzazione

· Bidirectional: viene effettuato prima l’upload incrementale e poi il download delle modifiche server.

Nella sezione Server Configuration è fondamentale indicare i campi della tabella sul database server da utilizzare per individuare gli insert e le modifiche: le query generate infatti si basano su una clausola WHERE per individuare solo gli aggiornamenti effettuati dopo l’ultima sincronizzazione da parte del client: le ancore agli ultimi valori sono supportati nativamente da SQL CE fin dalla versione 1.0 come vedremo più avanti.

Sempre nella sezione Server Configuration è importante indicare la tabella in cui verranno accolte le cancellazioni effettuate server side e il campo da utilizzare per individuare queste eliminazioni di record.

Dopo aver premuto OK il database server si presenta così:

clip_image010

Nella tabella tabFeedbacks sono stati aggiunti due campi LastEditDate e CreationDate (indicati nel designer nella sezione Server Configuration) per memorizzare la data di modifica e di creazione dei recordo: tali campi vengono valorizzati dai due trigger omonimi come si può vedere dalla figura sopra. Viene creata, sempre secondo i valori indicati nel designer, la tabella _Tombstone, alimentata anch’essa dal trigger DeletionTrigger a fronte di ogni cancellazione effettuata.

Sui campi citati vengono montati degli indici per rendere efficiente la ricerca delle modifiche effettuate quando viene avviata la fase di sincronizzazione.

Il database lato client, creato e sincronizzato subito al termine del wizard, si presenta così:

clip_image012

Oltre ai campi sincronizzati troviamo alcuni campi di sistema (iniziano con un doppio “_”) che consentono al motore di SQLCE di tenere traccia delle modifiche lato client. Da sempre l’engine di SQLCE utilizza campi di sistema per tenere traccia delle modifiche nativamente, visto che su SQL CE non è possibile creare dei trigger: non occorre in ogni caso modificare da codice tali valori.

Su l database SQLCE vengono create anche alcune tabelle:

· __sysOCSDeletedRows

· __sysOCSTrackedObjects

· __sysSyncArticles

· __sysTxCommitSequence

La prima tabella tiene le righe cancellate lato client, la seconda contiene l’elenco degli oggetti da tenere sotto controllo durante le normali operazioni sul DB, la terza tabella, ben conosciuta a chi ha usato la merge replication, tiene l’elenco delle tabella sotto replica, mentre l’ultima tiene traccia della sequenza delle operazioni transazionali andate a buon fine: sono tutte tabelle di sistema non visibili dall’interfaccia di amministrazione di SQL CE (per elencare le tabelle di sistema si può utilizzare select * from information_schema.tables, mentre per vederne il contenuto è sufficiente una semplice select).

Per effettuare una sincronizzazione è sufficiente utilizzare il codice seguente:

LocalDataCacheDevCon2006_FeedbackSyncAgent syncAgent = new LocalDataCacheDevCon2006_FeedbackSyncAgent();

Microsoft.Synchronization.Data.SyncStatistics syncStats = syncAgent.Synchronize();

La prima riga di codice crea l’oggetto syncAgent (la classe è stata generata in automatico dal designer di Visual Studio) e la seconda riga invoca il metodo Synchronize. Tale metodo restituisce un oggetto di tipo SyncStatistics da cui è possibile capire il numero delle modifiche inviate, il numero delle modifiche ricevute per ogni tabella sincronizzata.

E’ possibile modificare, come accennato all’inizio dell’articolo, il comportamento di replica agendo sulle proprietà della classe derivata da SyncAgent. Ad esempio prima di lanciare la replica è possibile impostare la direzione della replica anche da codice:

LocalDataCacheDevCon2006_FeedbackSyncAgent syncAgent = new LocalDataCacheDevCon2006_FeedbackSyncAgent();

// Decido la direzione

syncAgent.tabFeedbacks.SyncDirection =
Microsoft.Synchronization.Data.SyncDirection.Snapshot;
Microsoft.Synchronization.Data.SyncStatistics syncStats = syncAgent.Synchronize();

In questo caso, a prescindere dai parametri indicati nel designer di Visual Studio, stiamo forzando una sincronizzazione di tipo SnatpShot ovvero la ricrezione della tabella lato client e lo scarico di tutti i dati della tabella server.

Come abbiamo indicato precedentemente, Visual Studio 2008, crea anche le classi SyncAdapter server side; il compito di tali classi è specificare i comandi da lanciare sul DB per gestire gli inserimenti, le modifiche e il recupero (incrementale o meno) delle righe modificate. Ecco l’estratto della classe SyncAdapter relativo alla nostra tabella tabFeedbacks:

public partial class tabFeedbacksSyncAdapter : Microsoft.Synchronization.Data.Server.SyncAdapter {
private void InitializeCommands()
{

// tabFeedbacksSyncTableInsertCommand command.

this.InsertCommand = new System.Data.SqlClient.SqlCommand();

this.InsertCommand.CommandText = @" SET IDENTITY_INSERT
dbo.tabFeedbacks ON INSERT INTO dbo.tabFeedbacks ([idFeedback], [FeedbackGUID], [FeedbackTechnology], [FeedbackLevel], [FeedbackSlot], [FeedbackComment], [LastEditDate], [CreationDate]) VALUES (@idFeedback, @FeedbackGUID, @FeedbackTechnology, @FeedbackLevel, @FeedbackSlot, @FeedbackComment, @LastEditDate, @CreationDate” ;
// tabFeedbacksSyncTableDeleteCommand command.

this.DeleteCommand = new System.Data.SqlClient.SqlCommand();

this.DeleteCommand.CommandText = "DELETE FROM dbo.tabFeedbacks WHERE ([idFeedback] = @idFeedback) SET @sync_row_cou" +

"nt = @@rowcount";

// tabFeedbacksSyncTableUpdateCommand command.

this.UpdateCommand = new System.Data.SqlClient.SqlCommand();

this.UpdateCommand.CommandText = @"UPDATE dbo.tabFeedbacks SET [FeedbackGUID] = @FeedbackGUID, [FeedbackTechnology] = @FeedbackTechnology, [FeedbackLevel] = @FeedbackLevel, [FeedbackSlot] = @FeedbackSlot, [FeedbackComment] = @FeedbackComment, [LastEditDate] = @LastEditDate, [CreationDate] = @CreationDate WHERE ([idFeedback] = @idFeedback) SET @sync_row_count = @@rowcount";

// selectIncrementalInsertsCommand command.

this.SelectIncrementalInsertsCommand = new System.Data.SqlClient.SqlCommand();

this.SelectIncrementalInsertsCommand.CommandText = "SELECT * FROM [tabFeedbacks]";

this.SelectIncrementalInsertsCommand.CommandType = System.Data.CommandType.Text;

// tabFeedbacksSyncTableSelectConflictDeletedRowsCommand command.

this.SelectConflictDeletedRowsCommand = new System.Data.SqlClient.SqlCommand();

this.SelectConflictDeletedRowsCommand.CommandText = "SELECT [idFeedback], [DeletionDate] FROM [tabFeedbacks_Tombstone] WHERE ([idFeedback] = @idFeedback)";

// tabFeedbacksSyncTableSelectConflictUpdatedRowsCommand command.

this.SelectConflictUpdatedRowsCommand = new System.Data.SqlClient.SqlCommand();

this.SelectConflictUpdatedRowsCommand.CommandText = "SELECT [idFeedback], [FeedbackGUID], [FeedbackTechnology], [FeedbackLevel], [FeedbackSlot], [FeedbackComment], [LastEditDate], [CreationDate] FROM dbo.tabFeedbac" +

"ks WHERE ([idFeedback] = @idFeedback)";

// tabFeedbacksSyncTableSelectIncrementalInsertsCommand command.

this.SelectIncrementalInsertsCommand = new System.Data.SqlClient.SqlCommand();

this.SelectIncrementalInsertsCommand.CommandText = @"SELECT [idFeedback], [FeedbackGUID], [FeedbackTechnology], [FeedbackLevel], [FeedbackSlot], [FeedbackComment], [LastEditDate], [CreationDate] FROM dbo.tabFeedbacks WHERE ([CreationDate] > @sync_last_received_anchor AND [CreationDate] <= @sync_new_received_anchor)";

// tabFeedbacksSyncTableSelectIncrementalDeletesCommand command.

this.SelectIncrementalDeletesCommand = new System.Data.SqlClient.SqlCommand();

this.SelectIncrementalDeletesCommand.CommandText = "SELECT [idFeedback], [DeletionDate] FROM [tabFeedbacks_Tombstone] WHERE (@sync_initialized = 1 AND [DeletionDate] > @sync_last_received_anchor AND [DeletionDate]" +

" <= @sync_new_received_anchor)";

// tabFeedbacksSyncTableSelectIncrementalUpdatesCommand command.

this.SelectIncrementalUpdatesCommand = new System.Data.SqlClient.SqlCommand();

this.SelectIncrementalUpdatesCommand.CommandText = @"SELECT [idFeedback], [FeedbackGUID], [FeedbackTechnology], [FeedbackLevel], [FeedbackSlot], [FeedbackComment], [LastEditDate], [CreationDate] FROM dbo.tabFeedbacks WHERE ([LastEditDate] > @sync_last_received_anchor AND [LastEditDate] <= @sync_new_received_anchor AND [CreationDate] <= @sync_last_received_anchor)";

}

}

Formattazione complicata per un articolo a parte, i nomi dei comandi sono chiari e non necessita di spiegazione: vengono creati i comandi per esegure le INSERT, gli UPDATE, i DELETE rispetto alle modifiche inviate dai client e i tre comandi per rintracciare, a fronte di una operazioni di sincronizzazione, le modifiche effettuate sul server da inviare al client in modo incrementale.

In base al tipo di sincronizzazione scelto nel designer di Visual Studio vengono generati solo i comandi necessari: ad esempio, se la sincronizzazione è di tipo upload-only non vengono generati i comandi per rintracciare le modifiche effettuate al server, così come se la sincronizzazione è di tipo download-only non vengono generati i comandi per applicare le modifiche al server.

Vista la natura dei comandi generati (non sono stored procedure, le modifiche vengono rintracciate per data di modifica, i dati non vengono partizionati a priori) ADO.NET Sync Service non si adatta a scenari con centinaia di migliaia di record oppure a scenari in cui le modifiche vengono partizionate per zone o per client (territorialità dei dati) che vengono invece brillantemente risolte da tecnologie più corpose e complete come la Merge Replication. Il messaggio che mi preme far passare è che ADO.NET Sync Service è il primo passo di una lunga strada e quindi si adatta benissimo a scenari semplici in cui lo sviluppatore vuole avere il controllo completo e dove non è possibile utilizzare la Merge Replication. Per scenari più “corposi” in cui occorre partizionare molte tabelle con molti record in base al client occorrono tecniche più efficienti di utilizzo dei dati (non si può lanciare una query su 100.000 record per estrarre solo le modifiche destinate ad un agente di vendita ma occorre partizionarle a priori, gestendo anche l’eventuale, ma frequente cambio di territorialità dei dati), tecniche che la Merge Replication espone in modo completo.

Per questo primo articolo introduttivo è tutto, ci risentiamo presto con un articolo di approfondimento sulle classe generate e sulle tecniche per raggruppare i dati, gestire dati per singolo client e passare parametri al motore di replica.

Roberto Brunetti
MCP, MCSD.NET, MCSE + I, MCT
roberto@devleap.it
http://blogs.devleap.com/rob
www.thinkmobile.it

VISUAL STUDIO 2008, .NET FW e CF 3.5

Articoli pubblicati su week.it che ho riuniuto in un unico post.

Uscita la Beta 2 di .NET 3.5 e Visual Studio 2008 (ormai siamo alla RTM, ma era bello lasciare questa frase di inizio agosto che ci ricorda il caldo e le ferie J è giunto il momento di iniziare una serie di articoli settimanali per analizzarne le novità indicando, ove possibile, i puntatori verso informazioni più corpose.

Per prima cosa occorre separare nettamente cosa offre la nuova versione del Framework .NET e quali strumenti mette a disposizione Visual Studio 2008 a supporto delle nuove feature, senza dimenticare i nuovi strumenti indipendenti dalla versione del Framework. Con questa frase voglio sottolineare, se ce ne fosse ancora bisogno, che la piattorma .NET offre, da sempre, librerie e componenti utilizzabili senza l’ausilio di Visual Studio. Dall’altra parte, Visual Studio, in base all’edizione scelta, fornisce non solo strumenti che automatizzano e facilitano l’utilizzano di alcune di queste librerie e componenti, ma fornisce strumenti di supporto per la gestione del ciclo di vita di un software, per l’analisi del codice sorgente e del codice in esecuzione, per la definizione visuale di classi, diagrammi applicativi e di deployment e non ultimo strumenti per la gestione di test sul codice. Quindi se da una parte potremmo scrivere applicazioni, anche complesse, senza utilizzare Visual Studio, dall’altra parte, lo strumento è diventato un alleato importante e indispensabile per la gestione dei progetti software.

Nei vari articoli che seguono, nelle varie settimane, analizzeremo separatamente, le novità che riguardano la piattaforma, come l’integrazione di AJAX nel motore ASP.NET, i nuovi costrutti C# e VB, l’introduzione di LINQ per citarne alcuni, e le novità che riguardano l’ambiente di sviluppo, non tanto rispetto alle novità del Framework, quanto rispetto agli strumenti di supporto della soluzione software, come Unit Testing, nuove funzionalità di refactoring, nuovi designer che appunto prescindono dalla versione del Frameowrk utilizzato: ad esempio, le nuove funzionalità di refactoring possono lavorare anche su progetti .NET FW 2.0/3.0.

Chiudiamo questo primo articolo della serie con un chiarimento sulle versioni con cui lavoreremo: ad oggi, come saprete, i compilatori .NET sono in versione 2.0, versione indicata anche per i linguaggi (C# è in versione 2.0, VB.NET è in versione 8, ovvero la seconda versione di VB.NET dopo la 6.0 che allineata al vecchio mondo COM); il .NET Compact Framework è in versione 2.0 (SQLCE è in versione 3.1), mentre il Framework completo è in versione 3.0: la versione 3.0 ha portato novità con l’aggiunta delle librerie WCF, WPF, WF che si utilizzano ancora con C# 2.0 (e VB.NET 8) e, appunto, i compilatori in versione 2.0.

La versione 3.5 “complica ancora un po’” lo scenario: i compilatori fanno un salto di versione passando alla 3 (quindi avremo C# 3.0 e VB.NET 9), il runtime passa alla versione 3.5 inglobando anche molte librerie ad oggi disponibili come download separato. Il Framework è quindi in versione 3.5 così come il Compact Framework passa alla versione 3.5 e si porta dietro SQL Compact Edition versione 3.5. Visual Studio è invece in versione 2008 e consente la creazione di progetti che si basano sul runtime del Framework 2.0, 3.0 (in pratica versione 2.0 più WPF, WCF, WF) e versione 3.5. Sviluppando un progetto versione 3.5 si ottengono le reference (o si devono fare a mano le reference J) verso le librerie 2.0 per quanto riguarda le funzionalitá base (ad esempio la System.Transaction), verso le librerie 3.0 per quanto riguarda le classi aggiunte nella versione 3.0 (WPF, WCF, WF, WCS) e/o verso le librerie versione 3.5 per le novitá introdotte: queste ultime sono nuove librerie, come il caso di LINQ, rivitazioni di librerie esistenti, come nel caso della System.Web.Extension, oppure aggiunte a funzionalitá della 3.0, come ad esempio i servizi di hosting di workflow in WCF (WorkflowServiceHost).

Mobile Development

La nuova versione di Visual Studio viene equipaggiata con template e SDK per le piattaforme Pocket PC 2003, Windows CE, Windows Mobile 5.0 Pocket PC e Windows Mobile 5.0 SmartPhone e supporta la creazione/gestione di progetti basati sul .NET Compact Framework 2.0 e 3.5. E’ anche possibile convertire un progetto dalla versione .NET CF 2.0 alla versione 3.5. In pratica scegliendo la versione vengono proposte le reference corrette agli assembly .NET nelle varie versioni e agganciato il compilatore allineato alla versione del linguaggio utilizzato. Come abbiamo accennato nel primo articolo della serie, verrà utilizzato il compilatore C# versione 3.0 per progetti .NET CF 3.5 e l’attuale compilatore C# 2.0 per progetti in versione 2.0.

Gli emulatori utilizzano il Device Emulator 2.0 (disponibile oggi al download e installabile anche con Visual Studio 2005), mentre il Device Emulator 3.0 è installabile, almeno per adesso, come download separato. La nuova piattaforma di emulazione fornisce il Device Configuration Manager che elimina la necessità attuale di comporre manualmente file xml per modificare la configurazione degli emulatori. Risulta quindi molto semplice modificare le impostazioni di security per aderire a quelle dei device in commercio: con semplici selezioni da una interfaccia grafica si può lavorare One-Tier, Two-Tier, Locked o Prompt.

Una delle novità più interessanti è sicuramente la possibilità (offerta anche dalla versione Professional) di creare Unit Test su codice .NET CF e eseguirli su device o emulatore. La funzionalità è molto simile a quanto oggi troviamo in Visual Studio Team System for Tester: in pratica sono state aggiunte le librerie mobile per eseguire i test e collezionarne i risultati da riportare nell’IDE di Visual Studio. I risultati possono poi essere pubblicati, associandoli ad una Build, in Team Foundation Server.

Upgrade

Quando si apre un progetto/solution VS 2005 in VS 2008 vengono aggiornati i file di progetto e della solution al nuovo formato.

Occorre tenere presente che:

  • Un progetto .NET CF 1.0 viene aggiornato (come reference) alla versione 2.0 del .NET CF
  • Un progetto .NET CF 2.0 rimane invariato, non viene quindi portato alla versione 3.5 del runtime
  • I riferimenti a SQLCE 3.0 (SQL 2005 Mobile Edition) e SQLCE 3.1 vengono aggiornati a SQL CE 3.5
  • I progetti SmartPhone 2003 vengono aggiornati a Windows Mobile 5.0 for SmartPhone

Dopo la conversione, su ogni progetto, con tasto dx, è possibile aggiornare le librerie al .NET CF 3.5. 

E' poi possibile, come in VS 2005, modificare la "Target Platform" per portare i progetti da una piattaforma all'altra.

Per quanto riguarda SQL CE, oltre all'ormai famoso upgrade.exe che consente sul device di aggiornare il database .sdf alle nuove versioni (era presente anche in SQLCE 3.0 e SQLCE 3.1), è possibile convertire i database direttamente da VS 2008. E' sufficiente aprire il file sdf dal progetto (o da dove volete ovviamente) per poter effettuare l'upgrade al volo.

Piú avanti vedremo le novità del .NET CF 3.5 come LINQ e WCF e gli strumenti del .NET CF 3.5 SDK per eseguire profiling e analisi delle performance di una applicazione. Come abbiamo avuto modo di chiarire nel precedente articolo, questi strumenti sono indipendenti da Visual Studio.

Visual Studio 2008 for Mobile Dev

Il .NET CF 3.5 adesso installa le stringhe di risorse sul device/emulatore tramite un nuovo cab denominato NETCFv35.Messages.EN.CAB che si trova sotto x:\program files\Microsoft.NET\SDK\CompactFramework\v3.5\windowsce\Diagnostics.

La creazione di un nuovo progetto presenta una nuova maschera, simile a quanto avveniva in VS 2003: non si sceglie il progetto dall'alberino delle varie solution disponibili, ma è sufficiente scegliere Smart Device: una volta scelto il tipo di progetto in una seconda maschera si sceglie la tipologia di piattaforma e poi la versione del .NET CF da utilizzare per le reference e per la distribuzione del runtime sul device. Si può optare per .NET CF 2.0 o per .NET CF 3.5.

N.B. le immagini incluse sono ridotte come dimensione: accanto ad ognuna il link verso la dimensione reale.

Questa la prima maschera:

http://thinkmobile.it/photos/orcas/images/6138/425x323.aspx

Come si nota le piattaforme per cui è installato nativamente l'SDK sono Pocket PC 2003, Windows CE, Windows Mobile 5.0 for Pocket PC e SmartPhone.

Una volta scelta la piattaforma si sceglie la versione del .NET CF da utilizzare:

http://thinkmobile.it/photos/orcas/images/6139/425x323.aspx

 Dopo la scelta della versione del .NET CF, come sempre scegliere Device Application, Class Library e così via per creare il tipo di progetto.

Il designer delle Windows Form (visto che WPF non è disponibile sul .NET CF 3.5) si presenta molto simile al precedente: si può scegliere il form factor da assegnare ad ogni form e ruotare lo schermo del designer come nella versione 2005 di VS.

http://thinkmobile.it/photos/orcas/images/6140/425x309.aspx

Anche la toolbox si presenta più o meno identica. Questo l'elenco dei controlli:

http://thinkmobile.it/photos/orcas/images/6141/81x425.aspx

La configurazione dell'emulatore da Visual Studio prevede quanto conosciamo con l'attuale Device Emulator 2.0 e consente la gestione del livello della batteria: questa funzione risulta molto comoda per testare un'applicativo power-aware (come dovrebbero essere tutti): è inutile lanciare una operazione lunga di analisi sui dati, ad esempio, se resta il 2% di batteria.

http://thinkmobile.it/photos/orcas/images/6142/425x328.aspx

Molto interessante il nuovo Device Configuration Manager, primo fra gli strumenti per facilitare la configurazione di device e emulatori: ad oggi è necessario comporre i file .xml di provisioning e "installarli" tramite rapiconfig.exe. Con questo nuovo strumento risulta molto semplice leggere la configurazione, modificarla e vedere le differenze fra la configurazione desiderata e quella attuale. Si possono importare anche i nostri file di provisioning esistenti per una facile migrazione al nuovo strumento.

http://thinkmobile.it/photos/orcas/images/6144/425x284.aspx

Risulta molto semplice così testare l'applicazione firmata o non firmata sulle varie configurazioni dei device One-Tier, Two-Tier, Locked, Prompt e così via.

Tramite questo strumento è possibile visualizzare i certificati digitali installati su device e emulatori, installarne di nuovi e verificarne i dettagli. Una nota, i nomi dei certificate store sono cambiati: non abbiamo più il privileged e unprivileged, ma Privileged Store e Standard Store, dove il secondo rappresenta lo store per i certificati con cui le applicazioni possono girare in normal-mode su device two-tier.

http://thinkmobile.it/photos/orcas/images/6143/425x285.aspx

Il .NET CF Remote Performance Monitor consente, nella nuova versione di fare un "attach to process" rendendo più semplice l'analisi di una porzioni di applicazione: la versione attuale deve lanciare l'applicazione e quindi ci costringe a visualizzare i dati complessivi di tutta l'applicazione fino a raggiungere il punto in cui si desidera effettuare le verifiche. La parte device-side viene installata in automatico dallo strumento senza bisogno di copiare manualmente i file nella directory \Windows: qualche problemino sulla mia Beta non consente di eseguire questa operazione in automatico e quindi ho dovuto comunque copiare i file a mano. I nuovi file device-side hanno nomi diversi dai precedenti e più precisamente sono: rtf3_5.dll e rtfhost3_5.exe. Tali file si trovano sempre nella directory dell'SDK del .NET CF 3.5 x:\program files\Microsoft.NET\SDK\CompactFramework\v3.5: ricordatevi di scegliere poi la directory corretta in base al processore del device; per gli emulatori si utilizza sempre la versione ARM.

Nella prossima immagine la directory con gli strumenti lato PC di sviluppo. Oltre al .NET CF RPM, troviamo LogViewer, già presente nella versione 2.0 SP1/SP2 e due nuovi strumenti:

http://thinkmobile.it/photos/orcas/images/6146/425x319.aspx

Il primo NETCFCLRProfiler è una versione ridotta (e per la verità anche diversa) del Profiler del Framework completo. Consente di analizzare nel dettaglio un'applicazione in esecuzione: anche in questo caso ci si può "attaccare" ad un processo già avviato e l'installazione delle dll lato device è automatica (come sempre sono sfigato e ho dovuto copiare a mano clrpro3_5.dll sul device). Lo strumento visualizza anche sotto forma di flusso grafico le chiamate fra i vari metodi consentendo una semplice (si fa per dire quando si parla di profiling in generale) individuazione dei punti della call stack che possono dare problemi.

Come abbiamo accennato, il compact frameowrk 3.5 arriva con qualche dll in più per supportare LINQ e WCF (sempre in versione ridotta: entrambi sono c.a. 250KB come obiettivo nella versione finale) e i nomi dei cab sono stati leggermente rivisti.

http://thinkmobile.it/photos/orcas/images/6147/425x229.aspx

 Nella System.ServiceModel si trovano le "porzioni" del motore di WCF e il binding basicHttpBinding, mentre in Microroft.ServiceModel.Channels.Mail.* il nuovo canale (non disponibile in WCF su desktop) WindowsMobileMailBinding che consente lo scambio di messaggi SOA sfruttando il canale della posta elettronica fra device (Pocket Outlook) e  Exchange 2007; ricordo che Exchange 2007 supporta il push dei messaggi verso il device.

Come sempre le sottodirectory wce400 e wce500 contengono i cab per l'installazione reale su device o emulatore in base alla versione del sistema operativo. Ricordo che Windows Mobile 6.0 si basa sempre su Windows CE 5, per precisione sulla 5.2.

System.Data.Entities contiene invece le parti applicative dell'entitiy framework, mentre il provider è contenuto sotto System.Data.SqlServerCe.Entitiy.dll che arriva con l'installazione di Sql Server Compact Edition 3.5.

SQL CE 3.5 arriva con qualche piccola novità per i device e con grandi novità su utilizzato su desktop, Tablet o UMPC.

La directory di installazione sul pc di sviluppo è x:\program files\Microsoft SQL server Compact Edition\v3.5 e si presenta così:

http://thinkmobile.it/photos/orcas/images/6148/425x228.aspx

Come accennato, entity framework viene reso disponibile tramite System.Data.SqlServerCe.Entity, ma solo se utilizzato su PC, Tablet o UMPC: non è quindi disponibile per Windows Mobile.

L'installazione prevede diversi componenti:

1) SSCEVSTools-ENU.msi: installa i componenti design-time in Orcas sotto la classica directory x:\program files\microsoft visual studio 9\Common7\IDE. Questi componenti non devono essere distribuiti

2) SSCERuntime-ENU.msi: installa i componenti di runtime per desktop, tablet e UMPC. Sono indispensabili sia a runtime che a design time. Questo MSI installa anche i nuovi componenti per la versione desktop di SQCE 3.5: Microsoft Synchronization Services for ADO.NET (OCS) e la già citata System.Data.SqlServerCe.Entity.dll.

3) SSCEDeviceRuntime.msi: installa i componenti destinati ai device e emulatori sulla macchina. Questi componenti sono necessari per l'integrazione con VS Orcas anche sulla macchina di sviluppo.

Le novità che abbiamo bollato come minori (rispetto appunto a EntityFramework e OCS) riguardano soprattutto il query processor :

- data type di tipo timestamp

- nested query

- CROSS apply e OUTER APPLY

- CAST

- TOP (finalmente !!!!!) diventa così più semplice paginare i dati per la loro visualizzazione nei minuscoli schermi

Oltre a OCS e Entity Framework, SQL CE 3.5, se utilizzato sul desktop, fornisce la possibilità di rientrare in una transazione creata con la System.Transaction 2.0: in due parole una operazione su SQL CE 3.5 può essere inserita all'interno del TransactionScope.

I Book On Line non sono ancora disponibili.

Abbiamo accennato nei post precedenti come in Visual Studio Orcas sia possibile effettura Unit Testing su device (o emulatore): credo che questa funzionalità, affiancata dal nuovo .NET CF RPM e dal profiler, siano le novità più importanti e utili della nuova versione.

Tra l'latro in Orcas gli strumenti di Unit Testing non sono più all'interno di Team System, ma disponibili nella versione Professional, almeno a quanto ci è dato sapere oggi.

Ecco le maschere di crezione di uno unit test, praticamente identiche (tranne un settaggio) a quanto oggi disponibile in VSTS:

http://thinkmobile.it/photos/orcas/images/6151/425x229.aspx

http://thinkmobile.it/photos/orcas/images/6153/425x285.aspx

Nella seconda immagine, come si può notare, la configurazione degli host prevede il tipo Smart Device con relativa piattaforma e scelta fra device e emulatore.

Se si crea una performance session su uno Unit Test il codice viene fatto girare sul desktop.

Anche senza l'automatismo in VS Orcas, oggi è possibile eseguire unit test su codice mobile, creando un progetto desktop con i sorgenti mobile linkati al suo interno e oppure compilazioni condizionali nel caso in cui il codice faccia uso di dispositivi, tipo lettore di codice a barre ad esempio, non disponibili sul desktop. Fra qualche giorno posso postare un mio articolo, scritto per Infomedia, proprio su questo argomento. La demo allegata all'articolo è già disponibile sul mio sito Think Mobile all'indirizzo http://thinkmobile.it/files/folders/mmdcii/entry5896.aspx.

Il nuovo Device Emulator 3.0 si presenta così:

http://thinkmobile.it/photos/orcas/images/6149/350x425.aspx

A parte la user interface pressochè identica, è possibile salvare la configurazione degli emulatori con Save As e riconfigurare l'emulatore. Il file di configurazione (.defcfg) è anche molto semplice da modificare a mano per cambiare al volo qualcosa senza ricorre alla user interface e soprattutto per poter scambiare la configurazione degli emulatori fra i membri di un team di sviluppo senza doverla ricreare su ogni PC di sviluppo.

http://thinkmobile.it/photos/orcas/images/6150/425x189.aspx

.NET Compact Framework 3.5

Il nostro filone su Visual Studio 2008 e .NET 3.5 prosegue con questo articolo dedicato alle novità del .NET Compact Framework versione 3.5. Le novità vedono l’introduzione di LINQ To SQLCE, Windows Communication Foundation, alcune API per lavorare con certificati digitali e qualche aggiunta alle classi Windows Forms. Oltre a questo troveremo un rivisto Remote Performance Manager e un nuovo CLR Profiler.

La versione 3.5 utilizza i compilatori in versione 3 (quindi avremo C# 3.0 e VB.NET 9), quindi molte novitá riguardano il linguaggio stesso e i compilatori. Anche SQLCE fa un salto in avanti presentandosi in versione 3.5. Avremo modo di parlare delle novitá del mini/db in un articolo separato.

l primo nuovo componente è Windows Communication Foundation: si tratta di un subset ridotto dell'attuale versione per il framework completo pensata per comunicazioni device-to-server, server-to-device e device-to-device (Peer to Peer).

Il subset di funzionalità prevede il trasporto via Http (BasicHttpBinding), un subset delle funzionalità di WS-Security e WS-Addressing, con la possibilità di estensioni custom, l'encoding basato su Text o algoritmi custom. Quanto non citato non è presente: manca quindi il supporto a Service e Contract Model, manca per adesso anche l'utility svcutil.exe che uscirà sotto forma di Power Toy successivamente.

E' stato creato un trasporto apposito per sfruttare il canale email per l'invio di messaggi WCF: il tutto è accessibile tramite WindowsMobileMailBinding (non presente nella versione completa sul .NET Framework) e sfrutta i servizi esposti da Exchange 2007 per lo store-and-forward dei messaggi. Tramite Exchange 2007 si sfrutta anche la possibilità di usare Push-Technology per inviare messaggi dal server ai device.

L’elenco completo delle features disponibili con WCF “mobile” rispetto alla versione Full è il seguente:

Feature

Desktop WCF

Compact WCF

Binding:    
· BasicHttpBinding Si Si
· CustomBinding Si Si
· WindowsMobileMailBinding N/A Si
· ExchangeWebServiceMailBinding Si, se si installa NetCF Si
Formatter:    
· SoapFormatter Si Si
· BinaryFormatter Si No
Encoder:    
· TextMessageEncoder Si Si
· BinaryMessageEncodingBindingElement Si No
· MTOMEncoder Si No
· GzipEncoder No No
Transport:    
· HttpTransportBindingElement Si Si
· HttpsTransportBindingElement Si Si
· MailTransportBindingElement Si, se si installa NetCF Si
· MsmqTransportBindingElement Si No
· TcpTransportBindingElement Si No
· (other transports)  Si No 
XmlDictionaryReader/Writer Si Si; stub sopra XmlTextReader/Writer
DataContractSerializer Si No; compatibile però con DCS via XmlSerializer
Service proxy generation SvcUtil.exe NetCFSvcUtil.exe (si trova nei Power Toys, non in VS2008
· Non-HTTP transports Si No
· Custom headers Si No
WS-Addressing Si Si
WS-Security message level security    
· X.509 Si Si
· Username/password Si No
· SecurityAlgorithmSuite.Basic256Rsa15 Si Si
· SecurityAlgorithmSuite.Basic256 Si No
WS-ReliableMessaging Si No
Patterns    
· Service model Si No
· Message layer programming Si Si
· Buffered messages Si Si
· Streaming messages Si No
· Endpoint descriptions in .config files Si No
Channel extensibility Si Si
Security channel extensibility Si No
 

Il secondo componente importante è LINQ, anch’esso subset del fratello maggiore: sono presenti LINQ to Object, LINQ to XML, LINQ to Dataset; nella Beta2 è apparso il supporto per LINQ to Entities e LINQ to SQL per adesso senza designer associato in Visual Studio 2008: occorre lavorare con Sql Metal per definire il modello. Per una introduzione su LINQ consiglio il libro Introducing LINQ di Paolo Pialorsi e Marco Russo e la relativa community www.introducinglinq.com.

La nuova versione si porta dietro nuovi strumenti di diagnostica: uno strumento centralizzato per abilitare/disabilitare le funzionalità di logging, dal finalizer log, al diagnostic log passando per Interop e statistiche.

Molto interessante il CLR Profiler, versione ridotta della versione del framework completo, che fornisce metodi per tracciare il comportamento delle applicazioni.

Il .NET Compact Framework Remote Performance Monitor 3.5 consente la visualizzazione della FReachable Queue e analisi più dettagliate sugli eventuali memory leak che, contrariamente a quanto pensano in molti, possono comunque verificarsi in ambiente .NET.

L’elenco completo degli strumenti della versione 3.5 del .NET Compact Framework é

.NET CF RPM: migliorato
CLR Profiler: nuovo
Logging Options: nuovo
Finalizer Log: nuovo
Network log: esistente
Native Interop
Loader Log

Gli strumenti non sono inclusi in Visual Studio 2008, ma arrivano come Power Tools, per adesso scaricabili da http://www.microsoft.com/downloads/details.aspx?familyid=c8174c14-a27d-4148-bf01-86c2e0953eab&displaylang=en&tm e in versione September CTP.

Una volta installato il tutto si puó utilizzare Logging Configuration per abilitare e disabilitare, su device e emulatori, le varie opzioni di logging:

  • Loader
  • Native Interop
  • Network
  • Error
  • Finalizer

Ogni logger scrive le informazioni in un file di log nella stessa directory dove gira l'applicazione.

Per effettuare analisi sul traffico di rete, i pacchetti spediti, i byte inviati e ricevuti é possibile usare il Network Logger Viewer che visualizza, in forma "grafica" il file di log relativo.

Ad esempio questo i log su una chiamata ad un servizio WCF in basicHttpBinding effettuata dall'emulatore.

http://devlab.devleap.it/RobertoB/Immagini/Posts/.NETCF3.5PowerToolsNetworkLogger_11A70/NetworkLoggerWCFRequest_thumb2.jpg

Nella prima griglia si vedono, in base ai timestamp, i vari record di invio/ricezione pacchetti e abilitando (come da figura) le colonne Bytes Sent e Bytes Received si puó facilmente analizzare quante informazioni sono state inviate.

Per ogni record, nella finestra sotto troviamo il dettaglio dei byte scambiati e lo stream relativo, mentre nella finestrina a destra si vede la rappresentazione testuale.

In questo esempio, la chiamata riguarda appunto un servizio WCF che accetta un valore intero e restituisce, come da figura sotto la scadenza di una polizza.

http://devlab.devleap.it/RobertoB/Immagini/Posts/.NETCF3.5PowerToolsNetworkLogger_11A70/NetworkLoggerWCFReply_thumb2.jpg

Questo e gli altri strumenti sono utilizzabili anche con applicazioni .NET CF 2.0, senza bisogno di nessuna ricompilazione

L'unica cosa che occorre fare è eseguire la "vecchia" (si fa per dire) applicazione 2.0 con il runtime versione 3.5. Per farlo occorre creare un file di configurazione (app.exe.config) che indica appunto di far girare l'applicazione con il 3.5 come segue:

<configuration>
  <startup>
    <supportedRuntime version="v3.5.xxxx"/>
  </startup>
</configuration>

dove xxxx sta per la build che state usando (Beta1, Beta2 o l'imminente RC). La Beta 2 attuale è 3.5.71210.

Un modo più semplice per farlo è usare NetCFCfg.exe direttamente dal device: questo softwarino consente di

  • Listare le versioni del .NET CF installate sul device
  • Visualizzare il contenuto della GAC
  • Editare la configurazione di default del device in base alle varie versioni installate
  • Editare appunto i file di configurazione delle applicazioni

L'exe può essere copiato a mano nella directory Windows: come sempre occorre prendere quello corretto in base a piattaforma e processore a partire dalla directory C:\Program Files\Microsoft.NET\SDK\CompactFramework\v3.5\WindowsCE (wce500 o wce400 e sottodirectory relativa al processore) o addirittura ottenere una copia automatica quando si attacca il device o l'emulatore ad ActiveSync e si sincronizza il tutto.

VSTS non solo Mobile

Alcuni screen shot che riguardano lo sviluppo con VSTS 2008 in generale.

Per prima cosa la parte server (Team Foundation Server) si presenta così

http://thinkmobile.it/photos/orcas/images/6292/640x480.aspx

Si basa su SharePoint v3 (di cui avremo modo di parlare alla SharePoint Conference). Il default web site espone le due classiche directory di reporting server, mentre il sito Team Foundation Server espone i servizi per Build, Services, Version Control, OLAP e Work Item Tracking.

Le varie applicazioni sono divise in 3 Application Pool che ospitano appunto i servizi TFS, la parte di reportistica e l'amministrazione di SharePoint.

Dal menù di un progetto è possibile generare le "metriche del codice"  (Code Metrics suona molto meglio) di cui abbiamo già accennato qualcosa nell'altro mio post sulla CTP di Marzo.

http://thinkmobile.it/photos/orcas/images/6293/640x480.aspx

Per capire meglio questa nuova funzionalità prendiamo ad esempio il seguente codice

http://thinkmobile.it/photos/orcas/images/6289/640x480.aspx

Una volta generato il Code Metrics si ottiene questo risultato.

http://thinkmobile.it/photos/orcas/images/6290/500x375.aspx

"Code Metrics" consente di capire se il codice di un progetto/solution è complesso da manutenere, il livello di coupling, la profondità gerarchica delle classi e l'ormai famoso indice di Cyclomatic Complexity (già presente nel Code Analysis della versione attuale in forma testuale).

Altra opzione "carina" è la gestione delle using di un sorgente C#. Dal menù contestuale si possono infatti organizzare le using:

http://thinkmobile.it/photos/orcas/images/6294/500x375.aspx

Ultimo screenshot: la versione VSTS for DB Pro 2008 presenta nativamente l'analisi del codice T-SQL tramite FXCop (che in realtà già dalla versione 2005 si chiama Code Analysis): queste le regole disponibili, immagino già note a molti:

http://thinkmobile.it/photos/orcas/images/6291/500x375.aspx

Power Tools VSTS 2008 Architect

Il nostro filone su Visual Studio 2008 e .NET 3.5 prosegue con questo articolo dedicato ad un add-in giá disponibile per Visual Studio 2008 Team System Architect Edition che prendeil nome di Power Tools.

Il componente nasce da una esigenza fondamentale nella progettazione di applicazioni distribuite basate su vari layer: nella versione 2005 di Visual Studio Team System Architect Edition non era possibile rappresentare nel diagramma AD (Application Diagram) progetti di tipo class library che, come da documentazione, dovevano essere considerati parte del progetto principale: in pratica un progetto Windows Form, oppure ASP.NET, oppure Web Service ospitava nel digramma tutte le dll referenziate.

Se da una parte, questa rappresentazione logica é corretta, dall’altra non consente di rappresentare tutti gli elementi di una soluzione Visual Studio dal punto di vista fisico. Noi, in DevLeap, avevamo optato per un workaround in modo da rappresentare in AD e DD (Deployment Diagram) i progetti di tipo DLL. Tutte le nostre implemtazioni fanno uso di UI Layer, composto da uno o piú progetti di tipo class library, di un Biz Layer che si appoggia a dei factory per l'accesso ai dati o la chiamata a servizi (Web Service o WCF). Utilizzavamo quindi le application di tipo “Generic Application” per ogni class library presente nella soluzione.

A tal proposito si vedano i post

http://blogs.devleap.com/rob/archive/2005/09/06/5670.aspx
http://blogs.devleap.com/rob/archive/2007/04/11/solution-che-accompagner-molte-demo-della-devcon-2007.aspx

In pratica il diagramma relativo alla parte BIZ/DAL evidenzia l'uso di Generic Application per rappresentare i progetti di tipo Class Library.

http://devlab.devleap.it/RobertoB/Immagini/Posts/VisualStudioTeamSystem2008ArchitectPower_E3EE/2VSTS2008PowerToolsEMADClassLibraryPreGeneric_thumb.jpg

In Visual Studio 2008 Architect Edition, a parte altre interessanti novitá, la situazione é rimasta praticamente invariata, a meno di non installare i Power Tools per la versione Architect. Per adesso sono allineati alla Beta 2 di VSTS 2008.

Con questo add-in per la versione 2008 é finalmente possibile rappresentare e soprattutto descrivere i progetti di tipo class library, legarli al diagramma SDM e come sempre, sincronizzarne le impostazioni con il progetto reale. Ogni connessione fra applicazioni e class library gestita dall’Application Diagram verrá poi gestita con una reference fra i progetti Visual Studio, cosí come ogni reference effettuata dai progetti si riflette sul diagramma tramite la visualizzazione della connessione. Il supporto two-way aderisce a quanto giá presente negli strumenti di design fino dalla versione 2005. La descrizione delle impostazioni relative ai progetti di tipo class library viene poi memorizzata in file .SDM direttamente nel progetto Visual Studio che rappresenta la dll stessa.

Ad esempio, partendo da un semplice esempio, é possibile rappresentare i progetti di tipo Class Library che appaiono nella toolbox dopo l'installazione dei Power Tools.

http://devlab.devleap.it/RobertoB/Immagini/Posts/VisualStudioTeamSystem2008ArchitectPower_E3EE/1VSTS2008PowerToolsAD_thumb.jpg

Ogni connessione fra applicazioni e class library verrá poi gestita con una reference fra i progetti Visual Studio, cosí come ogni reference effettuata dai progetti si riflette sul diagramma tramite la visualizzazione della connessione.

Tempo fa ho eseguito l'upgrade della nostra soluzione (presentata a DevCon 2005 e DevCon 2007) composta ormai da una settantina di progetti Visual Studio in unica solution: si veda il post http://blogs.devleap.com/rob/archive/2007/05/10/upgrade-to-orcas-beta-1.aspx.

Dopo aver montato i Power Tool ho deciso di ridisegnare AD e DD facendo uso dei progetti di tipo class library.

Giustamente il risultato che mi si é presentato riaprendo il diagramma dopo l'installazione é il seguente

http://devlab.devleap.it/RobertoB/Immagini/Posts/VisualStudioTeamSystem2008ArchitectPower_E3EE/4VSTS2008PowerToolsEMADClassLibraryPre_thumb.jpg

In pratica l'AD si é accorto delle varie reference a progetti class library dai progetti reali e ha rappresentato le "figurine" e le relative connection sul diagramma. I nomi dei progetti sono gli stessi dei nomi reali dei progetti .csproj a cui sono stati tolti in automatico, come da prassi, i ".".

Per eliminare le Generic Application che avevamo usato come placeholder nella versione 2005 occorre procedere eliminando prima tutti i file .SDM (delle generic application) dalla solution di Visual Studio e poi eliminare dal diagramma i relaitivi elementi grafici.

Gli SDM relativi alle applicazioni di tipo Class Library vengono memorizzati direttamente nel relativo progetto Visual Studio, come accade da sempre per i tipi di applicazioni gestiti dall'AD.

http://devlab.devleap.it/RobertoB/Immagini/Posts/VisualStudioTeamSystem2008ArchitectPower_E3EE/3VSTS2008PowerToolsReference_thumb.jpg

Altra operazione che avevamo fatto come workaround era stata quella di legare le class library dello strato DAL al database, operazione non piú necessaria in quanto il legame fra applicazione e DB sta giustamente nell'applicazione principale (Windows Form, WPF, ASP.NET che sia) ove infatti, da sempre, sono memorizzate le connection string nei rispettivi file .config.

Alla prossima

Sviluppo Mobile: Costruire una propria libreria

 

di Roberto Brunetti

Roberto è un libero professionista del gruppo DevLeap (www.devleap.com) sul cui sito si trovano articoli e blog tecnici sulle tecnologie legate allo sviluppo software in .NET. E’ specializzato in ASP.NET, Sviluppo mobile, Architetture distribuite e Visual Studio Team System. E’ l’autore del libro ASP.NET Full Contact edito da Mondadori Informatica e numerose pubblicazioni su riviste del settore. Ha partecipato come speaker a numerose conferenze del settore ed è MCT da 1997. È il fondatore della community www.ThinkMobile.it dedicata allo sviluppo mobile.

Dopo vari articoli su SQLCE 3.0 (che diventa installabile anche su Desktop con SQL Compact Edition 3.1) è arrivato il momento di dare uno sguardo alla scrittura di una propria libreria di classi per facilitare lo sviluppo di applicazioni. Questo articolo vuole essere una panoramica delle potenzialità spesso ignorate di Visual Studio 2005, non tanto per la produzione automatica di righe di codice (tecnica tra l’altro pericolosa in caso di grandi volumi di dati), quanto per la versatilità nella scrittura della libreria.

Sembra un articolo introdottivo, e in parte lo è, ma i concetti che vorrei passare, soprattutto dopo la prima parte, spero servano a sviluppare più velocemente testando l’applicazione sul desktop e con strumenti evoluti piuttosto che fare F5 e testare l’applicazione su device o emulatori.

In sequenza affronteremo la scrittura da zero di una classe molto semplice per leggere file di configurazione, feature assente nel .NET Compact Framework 2.0. Questo semplicissimo scheletro ci farà da guida per affrontare le modalità con cui noi di DevLeap (www.devleap.com) sviluppiamo applicazioni mobile. Cercheremo di scrivere e testare la libreria direttamente sul desktop per poi farne una analisi con gli strumenti di Visual Studio Team System esattamente come se fosse una libreria desktop.

Non è nel mio stile fare un articolo passo passo in quanto spesso preferisco cercare di andare in profondità sugli argomenti lasciando poi al lettore la fantasia di implementazione. Questa volta farò uno strappo alla regola e partiremo da zero in modo da mettere insieme i vari pezzi. Questo articolo non vuole essere però una guida per neofiti, quanto mettere in evidenza le potenzialità di uno strumento facendo capire passo passo gli step di sviluppo che adottiamo.

“Mi suona strano iniziare così”: aprite Visual Studio e create un nuovo progetto (utilizzeremo C#, ma il tutto è facilmente adattabile a VB.NET)

Creiamo un progetto C# - Smart Device di tipo libreria: scegliere la piattaforma (Pocket PC 2003, SmartPhone 2003, Windows CE 5.0, o Windows Mobile 5.0 xxx) è un dettaglio tralasciabile; come sapete questa selezione serve solo a utilizzare un template di Visual Studio che prepara lo scheletro applicativo con le reference corrette e qualche vincolo per evitare di usare librerie che potrebbero non girare sulla piattaforma target; per esempio, se scegliete Pocket PC 2003 non si vedranno le librerie Windows Mobile 5.0 nell’elenco delle librerie sotto Add Reference. In ogni caso, il codice che viene prodotto dalla compilazione è codice IL (o CIL) e come tale può girare ovunque giri il runtime del .NET Compact Framework 2.0. Nel caso di progetti “Device Application” la scelta, che ancora una volta non è vincolante, è più utile in quanto il designer di Visual Studio visualizza i form all’interno di device aderenti, come look & feel, alla piattaforma scelta. Ripeto: la scelta non è vincolante, ma è solo una facilitazione per trovare Reference e designer “adatti” alla piattaforma. Con Visual Studio 2005 è ancora possibile modificare la piattaforma scelta per un progetto dopo la creazione: è sufficiente premere tasto destro sul progetto e scegliere – Change Target Platform; volendo si può agire anche manualmente nei file di progetto in formato XML per allargare la scelta di possibili piattaforme.

Scelgo Windows Mobile 5.0, posiziono il tutto sotto c:\temp, nomino la Solution DevLeap.Sample, e il progetto DevLeap.Library.Mobile. Solution e progetto hanno nomi diversi semplicemente perché successivamente aggiungeremo altri progetti alla solution in modo da avere un client di test e progetti desktop per testare la nostra libreria.

Naming convention a parte questa la maschera di creazione progetto:

Appena creato il progetto cancelliamo la mitica Class1.cs e creiamo un nuovo sorgente C# denonimato Utility.cs.

Il progetto, a questo punto, ha una classe Utility in cui aggiungeremo i metodi appunto utili J nelle nostre applicazioni mobile. Il namespace per default è giustamente DevLeap.Library.Mobile.

Rendiamo pubblica la classe in modo da poterla richiamare dall’esterno e, se volete, sealed in modo da non poterla derivare ulteriormente e da non doverci preoccupare nella sua definizione di eventuali politiche di inheritance.

Questo il nostro progetto:

Fino a qui niente di nuovo immagino. Aggiungiamo un metodo per leggere il classico file di configurazione. Solitamente utilizzo questa tecnica: espongo un metodo GetAppConfigString che riceve in input il nome del file config e la key da leggere. Non calcolo in automatico il nome del config, come fa il .NET Framework completo per evitare “casini” di concatenazione sul nome del file da trovare; questo evita problemi di naming sul file .config che hanno, ad esempio, creato non pochi problemi nelle vecchie versioni di OpenNETCF. Preferisco passare un parametro in più piuttosto che lasciare alla libreria l’onere di trovare il nome corretto. Se preferite calcolare il nome in automatico, i metodi GetExecutingAssembly e GetCallingAssembly della classe Assembly possono darvi una mano.

Per evitare la lettura del config da disco (pardon, da scheda SD J) ad ogni richiesta, metto in cache il documento XML alla prima lettura. Ci servono quindi una variabile statica _xmlDoc (per rispettare la naming convention) e una variabile di tipo Object su cui effettuare la sincronizzazione in caso di applicazione multithread.

Ecco la prima parte del codice che inserisce in cache un XmlDocument nel caso in cui sia null:

if (Utility._xmlDoc == null)

{

lock (_xmlDocSyncLock)

{

if (Utility._xmlDoc == null)

{

XmlDocument xmlDoc = new XmlDocument();

string xmlDocPath = Utility.GetAppPath() + "\\"
+ configName;

XmlTextReader tr = new XmlTextReader(xmlDocPath);

xmlDoc.Load(tr);

tr.Close();

_xmlDoc = xmlDoc;

}

}

}

Prima di inserire il codice nel metodo corretto due informazione: stiamo usando un pattern .NET che, in questo caso, ci serve a caricare il documento XML nella variabile statica _xmlDoc. L’utilizzo del lock e della doppia if su _xmlDoc serve a evitare che più thread chiamanti vadano in conflitto durante l’assegnazione della variabile _xmlDoc.

Per leggere il file .config in formato XML (il classico file .config di .NET) ho utilizzato un XmlDocument che viene alimentato da un XmlTextReader. Per rintracciare la path del file config si utilizza un’altra funzione da aggiungere alla nostra libreria (Utility.GetAppPath) che vedremo tra un attimo.

Una volta assegnato il documento XML alla nostra variabile statica si procede alla sua lettura; ecco il metodo completo:

using System;

using System.Collections.Generic;

using System.Text;

using System.Xml;

namespace DevLeap.Library.Mobile

{

public sealed class Utility

{

private static XmlDocument _xmlDoc;

private static Object _xmlDocSyncLock = new Object();

public static string GetAppConfigString(string configName,
string key)

{

if (Utility._xmlDoc == null)

{

lock (_xmlDocSyncLock)

{

if (Utility._xmlDoc == null)

{

XmlDocument xmlDoc = new XmlDocument();

string xmlDocPath = Utility.GetAppPath() + "\\"
+ configName;

XmlTextReader tr = new XmlTextReader(xmlDocPath);

xmlDoc.Load(tr);

tr.Close();

_xmlDoc = xmlDoc;

}

}

}

String value = "";

XmlNode node = _xmlDoc.SelectSingleNode
("//configuration//appSettings//add[@key='" +
key + "']/@value");

if (node != null)

{

value = node.Value.ToString();

}

return value;

}

}

}

Per leggere la “key” ricevuta come argomento all’interno dell’albero dei nodi ho utilizzato una espressione XPath tramite il metodo SelectSingleNode. Nel caso in cui non trovi l’elemento di configurazione ho deciso di restituire String.Empty.

Inseriamo a questo punto la funzione GetAppPath:

public static string GetAppPath()

{

#if All

return Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);

#else

return Path.GetDirectoryName(Assembly.GetCallingAssembly().GetName().CodeBase);

#endif

}

Vedremo più avanti l’utilizzo della #if (compilazione condizionale); in pratica, visto che su Windows Mobile caricare tante DLL può essere un problema, solitamente scrivo l’applicazione su diversi layer (UI, BIZ, DAL, Factory, Entity e così via) e poi li confeziono in un unico exe sui device che possono avere il problema di caricamento. Vedremo come fare più avanti. Per adesso la #if All serve a chiamare il metodo Assembly.GetExecutingAssembly nel caso in cui il progetto sia confezionato con un unico exe oppure Assembly.GetCallingAssembly per ottenere l’assembly chiamante di questa libreria. In entrambi i casi prelevo poi il CodeBase che rappresenta la directory da cui è stato letto l’assembly in questione.

Per poter usare la classe Path e la classe Assembly occorrono due using (le reference sono già corrette come le ha impostate il template di Visual Studio): System.IO per Path e System.Reflection per Assembly. Ovviamente qualunque altra tecnica (compreso passare il path completo al file .config sono ugualmente valide).

A questo punto creiamo un progetto exe che utilizza la libreria: per uniformità creiamo un progetto Device Application per Windows CE 5.0 che chiameremo Applicazione. All’interno del progetto metteremo anche il file .config che useremo dalla libreria. Ho aggiunto il progetto dalla solution con tasto destro Add New Project e poi inserito un file xml chiamato Applicazione.Config.

Ecco il risultato

Il nome del file config, per uniformità, è Applicazione.config. Se preferite mantenere la naming convention delle applicazioni desktop usate app.config: occorre però stare attenti in quanto successivamente cercheremo di utilizzare questa libreria sul desktop e così facendo ritorneremo nel problema accennato in precedenza: il calcolo del nome del file config automatico.

A questo punto si può inserire un pulsante di test sul form per provare a leggere il file di configurazione; prima di aggiungere il codice occorre ovviamente una reference dal progetto Applicazione al progetto DevLeap.Library.Mobile. Il form conterrà poi il codice per leggere il .config che, com’è intuibile, è il seguente:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using DevLeap.Library.Mobile;

namespace Applicazione

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private void cmdReadConfig_Click(object sender, EventArgs e)

{

MessageBox.Show(Utility.GetAppConfigString
("Applicazione.config", "Test"));

}

}

}

Prima di eseguire il progetto su un emultatore o su un device occorre marcare il file Applicazione.config come Build Action = Content e come Copy To Output Directory = Always oppure Copy if Newer; queste impostazioni si scelgono dalla mascherina delle proprietà del file all’interno del progetto di Visual Studio e consentono appunto di eseguire il deploy come contenuto (non come compilazione ovviamente) del file di configurazione.

Eseguito il deploy e premuto il pulsante di test sul form (che ho chiamato cmdReadConfig) otteniamo ovviamente la stringa memorizzata nel file .config.

Proviamo quindi ad andare oltre: una volta creata la propria libreria, così come gli altri strati dell’applicazione occorre testare il tutto; testare il codice sul device è una procedura abbastanza lunga: per ogni modifica occorre rifare il deploy dell’applicazione, riavviare il debug (non c’è Edit & Continue sul device !). Debuggando il tutto sull’emulatore si va un po’ più veloci (soprattutto se collegate l’emulatore via DMA e usate la tastiera del pc per l’input), ma abbiamo sempre il problema di deploy per ogni modifica, l’impossibilità di usare Edit & Continue e soprattutto utilizziamo un “coso mobile” senza un file system comodo da visualizzare e editare.

Visual Studio Team System offre molti strumenti che facilitano il compito durante il test funzionale e il test di performance...ma…purtroppo questi strumenti non girano in ambiente Windows CE. Lo sviluppatore “accanito” però non si fa spaventare da questa limitazione della prima versione di Team System e si organizza J. Come ? Così !

Il Compact Framework è una versione ridotta del .NET Framework quindi, a parte qualche funzionalità specifica del .NET CF che non esiste su .NET FW completo (vedi IrDA ad esempio), tutto quello che funziona sul .NET CF funziona anche sul .NET FW completo. È disponibile un runtime del .NET CF 2.0 (anche della 1.0 in realtà) per processore X86 che ci consente di far girare il codice IL (o CIL) su Desktop.

Anche per SQLCE versione 3.0 è valido questo ragionamento. Si possono aprire e gestire file SDF sia da Visual Studio che da Sql Server 2005 Management Studio. Le librerie di SQLCE esistono anche per processore X86. Con SQL Compact Edition 3.0 (la 3.1 che al momento di scrittura di questo articolo – Dic 2006 – sta per uscire gira nativamente su desktop) è possibile, con poco lavoro, fare una reference da un progetto desktop alle librerie versione X86 per eseguire il codice di accesso ai dati su desktop; a tal proposito si veda il mio post di dicembre 2005; il post è su Team System, leggete l’ultima parte: http://blogs.devleap.com/rob/archive/2005/12/29/6428.aspx

Bene, abbiamo affermato che il codice si può testare sul desktop (vedremo come evitare l’utilzzo di barcode reader o librerie specifiche per l’ambiente mobile…tutto non si può avere J), vediamo come fare sul nostro semplicissimo progetto mobile composto da un exe e da una dll. Questa logica si può applicare, ed è quello che facciamo sui nostri progetti mobile reali, ad architetture più complesse seguendo sempre questi passi.

La sfiga (termine tecnico che sta a indicare generalmente una forma acuta di sfortuna) vuole che non si possa prendere il codice compilato per farlo girare sul desktop: questo non perché i compilatori siano diversi (vi garantisco che sono identici, anzi è proprio lo stesso csc.exe o vbc.exe a compilare i progetti mobile) ma perché le reference verso le librerie del framework sono diverse. Occorre quindi ricompilare il codice con le reference corrette per l’ambiente desktop.

Pronti? Iniziamo.

Per prima cosa creiamo un progetto di tipo Class Library normale (per il desktop) che per convenzione si chiamerà DevLeap.Library.Mobile.Desktop, così manteniamo i nomi allineati. Dopo la creazione togliamo tutti sorgenti all’interno e facciamo le stesse reference del progetto mobile: le reference vanno appunto fatte alle librerie del FW completo. Quindi se trovo una reference verso System.Xml nel progetto mobile farò una reference verso System.Xml del FW completo, se trovo un riferimento verso System.Windows.Form mobile farò una reference verso System.Windows.Form del FW completo.

Poi aggiungiamo i sorgenti del progetto mobile (Utility.cs nel nostro semplice caso). Nessuno di noi ha voglia di avere lo stesso codice in due posti diversi quindi non aggiungete il file normalmente, ma come LINK: questo consente di mantenere il sorgente “vero” nel progetto mobile, ma poterlo compilare, usare e modificare anche dal progetto desktop.

Dalla mascherina di Add Existing Item andate nella directory del progetto mobile (DevLeap.Library.Mobile nel nostro caso), selezionate tutti i sorgenti e poi premere il pulsantino nascosto accanto a Add: questa la maschera

Fate un Add as Link e non Add altrimenti il sorgente selezionato viene copiato nel progetto, cosa da evitare appunto per non raddoppiare i sorgenti.

Questo vale anche per i file reference.cs, per i file di configurazione (sempre che debbano essere identici), per i file che rappresentano i form (basta linkare il Formxxx.cs, non occorre prendere anche .designer.cs e .resx) e per i controlli custom (anche in questo caso prendere solo il Controxxx.cs; VS si preoccupa di linkare anche i file designer e resx).

Date una compilata al progetto Desktop per vedere se abbiamo tutte le reference corrette.

Proseguiamo poi con la creazione del progetto exe allineato all’eseguibile mobile: creare un Windows Application Project e referenziare DevLeap.Library.Mobile.Desktop (occorre prendere il progetto desktop ovviamente). Cancellare Form1.cs e Program.cs e poi aggiungere con la stessa tecnica dell’Add As Link Form1.cs, Applicazione.config e Program.cs dal progetto Applicazione. Per uniformità chiamerei il progetto desktop Applicazione.Desktop.

Questa la situazione attuale:

Come si nota i progetti desktop hanno i sorgenti dei rispettivi progetti mobile come Link (c’è un simbolino accanto al file) e le rispettive Reference. Ultima cosa: sul file Applicazione.config nel progetto desktop occorre impostare (come avevamo fatto per il progetto mobile) Build Action = Content e Copy to Output Directory = Copy Always o Copy If Newer.

Curiosi ? Avviate il progetto Applicazione.Desktop (fate tasto destro sul progetto, Debug, Start new instance) e come per magia ecco un form su XP (o Vista) con il form Mobile !!!

Questa tecnica funziona per qualunque controllo mobile supportato anche sul desktop. Ad esempio aggiungiamo un menù sul form mobile per capire cosa succede. Un consiglio: anche se si possono aprire i sorgenti linkati dal progetto .Desktop vi consiglio di editare i form sempre partendo dal progetto mobile; questo perché altrimenti la Toolbox di Visual Studio 2005 vi presenta tutti i controlli Windows.Form dell’ambiente desktop (giustamente) molti dei quali non esistono sul .NET CF. Aprendo invece i form dal progetto mobile avrete la toolbox corretta. Non preoccupatevi se ogni tanto riceverete il messaggio di errore “This document is opened by another project”: indica semplicemente che avete aperto un sorgente da un progetto e poi avete provato ad aprirlo da un altro progetto; è solo un warning che giustamente vi avverte che lavorate su un sorgente già aperto.

Per esempio: ho inserito sul form, dal progetto mobile, un po’ di controlli e un menù mobile. Questo il risultato sul desktop

Ovviamente il menù esce stile XP e non stile mobile e non ci sono le due soft key per rappresentare il menù.

Con il progetto desktop si può, solo per citare alcuni punti:

1) Lavorare con l’interfaccia

2) Testare il codice

3) Fare Edit & Continue durante il debug

4) Se l’applicazione lavora con il file system si può controllare il lavoro direttamente nella directory bin sul file system della macchina di sviluppo

5) Se l’applicazione scrive e legge file si possono editare dal file system del PC senza dover usare ActiveSync per copiare i file da e verso il device.

Ci sono una serie di cose che non si possono fare. Ad esempio

1) Testare librerie specifiche mobile come ad esempio BarCode Reader

2) Testare IrDA

3) Testare librerie Windows Mobile per Pocket Outlook

In questi casi uso la sequente tecnica: inserisco una direttiva di compilazione sul progetto Desktop oppure sfrutto le direttive #Pocket PC già inserite da Visual Studio sui progetti mobile per eliminare le righe che non funzionano sul desktop.

Ad esempio, in un applicativo che stiamo scrivendo adesso e che fa uso di librerie per lettori di codice a barre, questo è il codice per eliminare le parti non ammesse sul desktop. Siamo nel load di un form nello strato di User Interface che è divisa dall’eseguibile per essere sfruttata da più risoluzioni video.

private void MainForm_Load(object sender, EventArgs e)

{

UI.DummyCalls();

#if PocketPc

UI.CreateBrowserForm(new BrowserForm());

#endif

UI.ChangeState(ComeurOnline.Maui.UI.Common.BaseUI.FlowState.Login, txtRequest, lblError, lblRequest, treeLog, SendActionStepOutputMessageResponseStatus.Information, null, null, lblUserId, txtUserId, lblUserPassword, txtUserPassword, cmdLogin, cmdLogout);

#if PocketPc

// If we can initialize the Reader

if (BarCodeReader.InitReader())

{

// Create a new delegate to handle scan notifications

this._barCodeEventHandler = new
EventHandler(BarCodeReader_ReadNotify);

// Set the event handler of the Scanning class to our delegate

BarCodeReader.BarCodeEventHandler = this._barCodeEventHandler;

// Attach to activate and deactivate events

// this.Activated += new EventHandler(ReaderForm_Activated);

// Start a read on the reader

BarCodeReader.StartRead();

}

else

{

// Error

UI.ChangeState(ComeurOnline.Maui.UI.Common.BaseUI.FlowState.CommunicationError, txtRequest, lblError, lblRequest, treeLog, SendActionStepOutputMessageResponseStatus.Error, null, "BarCode Reader Error", lblUserId, txtUserId, lblUserPassword, txtUserPassword, cmdLogin, cmdLogout);

return;

}

#endif

}

Come si nota, Visual Studio “dipinge” di grigio il codice sotto compilazione condizionale. In questo caso, semplicemente “attiviamo” la nostra libreria per la lettura del codice a barre nel caso Pocket Pc: questa direttiva di compilazione è già inserita da VS 2005 in tutti i progetti mobile.

Anche se non è argomento di questo articolo, avere un progetto desktop per ogni progetto mobile della solution (un lavoro che costa circa 1 oretta di lavoro su un progetto reale: cronometrati 1 ore e 15 minuti sul progetto che stiamo seguendo adesso composto da 9 layer e quindi 9 progetti in cascata sul client mobile) consente poi di usare gli strumenti di Visual Studio Team System come Unit Testing, Code Coverage e Performance Session.

Update: Visual Studio 2008 consente la creazione e eseguzione di Unit Test direttamente dalla versione Professional. Gli unit test sono eseguibili anche su device e emulatore. In ogni caso mancano gli strumenti integrati di code coverage e performance session.

Per completezza riporto gli screenshot in cui dovrebbe essere facilmente leggibile anche il codice di Unit Test sul metodo GetAppConfigString, il risultato del Code Coverage del test e la maschera di solo sommario della Performance Session basata sull Unit Test.

Unit Test su GetAppConfigString (UtilityGetAppConfigStringTest):

 

Code Coverage su Unit Test UtilityGettAppConfigStringTest


Performance Session su Unit Test UtilityGettAppConfigStringTest

Per avere un’idea del carico sotto stress si può simulare l’accesso allo unit test da parte di uno o più utenti (simulazione valida anche per più thread) per un tempo stabilito. In VSTS questa tecnica implica l’utilizzo di un Load Test basato sullo Unit Test; sono 3 click di mouse per creare la versione base:

In un solo minuto abbiamo fatto 36.023 chiamate alla nostra funzione e direi che dai risultati (che non posso incollare in questo articolo per motivi di spazio, ma che potete analizzare voi stessi scaricando gli esempio) il tutto gira molto bene...e ci mancherebbe visto che abbiamo scritto una sola funzione J Applicate il ragionamento ad un progetto reale e tutto il tempo che risparmiate nello sviluppo su desktop potete investirlo in test più accurati.

N.B. Nel Load Test ovviamente otteniamo dei warning (39 threshold violation per l’esattezza) sul processore in quanto spesso il processore della macchina va oltre il 95%: la situazione è più che normale visto che “stressante e stressato” (Test e applicazione J) sono sulla stessa macchina.

Con pochi passaggi, avendo un progetto desktop, siamo in grado di testare il codice, di vedere cosa implica l’esecuzione del codice e possiamo mettere sotto stress il tutto per capire cosa succede nell’utilizzo reale dell’applicazione. Ovviamente i dati di performance riguardano l’ambiente desktop, ma facendo gli opportuni “scaling” si può come girerà nell’ambiente mobile.

Il codice completo, compreso il semplice Unit Test, il Load Test per testare il carico, una Performance Session per capire l’allocazione di memoria e i tempi di chiamate, e l’analisi dinamica del codice con Code Coverage, sono disponibili su www.thinkmobile.it/files: il file da scricare, previa registrazione al sito, è Articolo Infomedia Lib Mobile.zip.

Sperando di avervi semplificato la vita durante lo sviluppo delle parti core di una applicazione mobile, dandovi la possiblità con un semplice “lavoretto” di testare il 90% della soluzione e lasciando sul device o emulatore (l’emulatore comunque non avrebbe BarCode Reader ad esempio) solo la parte finale dei test vi rimando alla nostra conferenza http://devcon2007.devleap.com dove avremmo modo di analizzare in varie sessioni anche lo sviluppo mobile oltre a .NET 3.0 per Desktop e Server.

Reference:

OpenNETCF: Libreria Shared Source scaricabile da www.opennetcf.org

Articolo su Progetti desktop/mobile in VSTS : http://blogs.devleap.com/rob/archive/2005/12/29/6428.aspx

Esempi di codice completi che ripercorrono l’articolo

www.thinkmobile.it/files

Visual Studio Orcas for Mobile Dev

Prime  impressioni sulla Beta1 di Orcas.

Ho installato il tutto su una macchina VMWare dedicando 1.4 GB alla Virtual Machine memore della quantità di memoria che "ciucciava" la CTP di Marzo.

Dalle prime prove mi sembra molto più snello e non supero quasi mai il primo GB di memoria: non c'è paragone neanche sulla velocità.

Nella mia installazione non appariva la toolbox e neanche la tollbat Standard: basta ovviamente attivarle e appaiono.

Nella virtual machine VPC scaricabile (ho preso la versione con VSTS e TFS) non c'è ActiveSync, quindi ho montato la 4.5. Manca anche il Windows Mobile 6.0 SDK come segnalato nei post precedenti: a MEDC hanno confermato che non ci sarà neanche nella versione finale e va installato a parte.

Il .NET CF 3.5 adesso installa le stringhe di risorse sul device/emulatore tramite un nuovo cab denominato NETCFv35.Messages.EN.CAB che si trova sotto x:\program files\Microsoft.NET\SDK\CompactFramework\v3.5\windowsce\Diagnostics.

 

La creazione di un nuovo progetto presenta una nuova maschera, simile a quanto avveniva in VS 2003: non si sceglie il progetto dall'alberino delle varie solution disponibili, ma è sufficiente scegliere Smart Device: una volta scelto il tipo di progetto in una seconda maschera si sceglie la tipologia di piattaforma e poi la versione del .NET CF da utilizzare per le reference e per la distribuzione del runtime sul device. Si può optare per .NET CF 2.0 o per .NET CF 3.5.

N.B. le immagini incluse sono ridotte come dimensione: accanto ad ognuna il link verso la dimensione reale.

 

Questa la prima maschera:

Come si nota le piattaforme per cui è installato nativamente l'SDK sono Pocket PC 2003, Windows CE, Windows Mobile 5.0 for Pocket PC e SmartPhone.

Una volta scelta la piattaforma si sceglie la versione del .NET CF da utilizzare:

 

 Dopo la scelta della versione del .NET CF, come sempre scegliere Device Application, Class Library e così via per creare il tipo di progetto.

 

Il designer delle Windows Form (visto che WPF non è disponibile sul .NET CF 3.5) si presenta molto simile al precedente: si può scegliere il form factor da assegnare ad ogni form e ruotare lo schermo del designer come nella versione 2005 di VS.

 

Anche la toolbox si presenta più o meno identica. Questo l'elenco dei controlli:

 

 

La configurazione dell'emulatore da Visual Studio prevede quanto conosciamo con l'attuale Device Emulator 2.0 e consente la gestione del livello della batteria: questa funzione risulta molto comoda per testare un'applicativo power-aware (come dovrebbero essere tutti): è inutile lanciare una operazione lunga di analisi sui dati, ad esempio, se resta il 2% di batteria.

 

 

Molto interessante il nuovo Device Configuration Manager, primo fra gli strumenti per facilitare la configurazione di device e emulatori: ad oggi è necessario comporre i file .xml di provisioning e "installarli" tramite rapiconfig.exe. Con questo nuovo strumento risulta molto semplice leggere la configurazione, modificarla e vedere le differenze fra la configurazione desiderata e quella attuale. Si possono importare anche i nostri file di provisioning esistenti per una facile migrazione al nuovo strumento.

 

 

Risulta molto semplice così testare l'applicazione firmata o non firmata sulle varie configurazioni dei device One-Tier, Two-Tier, Locked, Prompt e così via.

Tramite questo strumento è possibile visualizzare i certificati digitali installati su device e emulatori, installarne di nuovi e verificarne i dettagli. Una nota, i nomi dei certificate store sono cambiati: non abbiamo più il privileged e unprivileged, ma Privileged Store e Standard Store, dove il secondo rappresenta lo store per i certificati con cui le applicazioni possono girare in normal-mode su device two-tier.

 

 

Il .NET CF Remote Performance Monitor consente, nella nuova versione di fare un "attach to process" rendendo più semplice l'analisi di una porzioni di applicazione: la versione attuale deve lanciare l'applicazione e quindi ci costringe a visualizzare i dati complessivi di tutta l'applicazione fino a raggiungere il punto in cui si desidera effettuare le verifiche. La parte device-side viene installata in automatico dallo strumento senza bisogno di copiare manualmente i file nella directory \Windows: qualche problemino sulla mia Beta non consente di eseguire questa operazione in automatico e quindi ho dovuto comunque copiare i file a mano. I nuovi file device-side hanno nomi diversi dai precedenti e più precisamente sono: rtf3_5.dll e rtfhost3_5.exe. Tali file si trovano sempre nella directory dell'SDK del .NET CF 3.5 x:\program files\Microsoft.NET\SDK\CompactFramework\v3.5: ricordatevi di scegliere poi la directory corretta in base al processore del device; per gli emulatori si utilizza sempre la versione ARM.

Nella prossima immagine la directory con gli strumenti lato PC di sviluppo. Oltre al .NET CF RPM, troviamo LogViewer, già presente nella versione 2.0 SP1/SP2 e due nuovi strumenti:

 

 

Il primo NETCFCLRProfiler è una versione ridotta (e per la verità anche diversa) del Profiler del Framework completo. Consente di analizzare nel dettaglio un'applicazione in esecuzione: anche in questo caso ci si può "attaccare" ad un processo già avviato e l'installazione delle dll lato device è automatica (come sempre sono sfigato e ho dovuto copiare a mano clrpro3_5.dll sul device). Lo strumento visualizza anche sotto forma di flusso grafico le chiamate fra i vari metodi consentendo una semplice (si fa per dire quando si parla di profiling in generale) individuazione dei punti della call stack che possono dare problemi.

Il compact frameowrk 3.5 arriva con qualche dll in più per supportare LINQ e WCF (sempre in versione ridotta: entrambi sono c.a. 250KB come obiettivo nella versione finale) e i nomi dei cab sono stati leggermente rivisti.

 

 Nella System.ServiceModel si trovano le "porzioni" del motore di WCF e il binding basicHttpBinding, mentre in Microroft.ServiceModel.Channels.Mail.* il nuovo canale (non disponibile in WCF su desktop) WindowsMobileMailBinding che consente lo scambio di messaggi SOA sfruttando il canale della posta elettronica fra device (Pocket Outlook) e  Exchange 2007; ricordo che Exchange 2007 supporta il push dei messaggi verso il device.

Come sempre le sottodirectory wce400 e wce500 contengono i cab per l'installazione reale su device o emulatore in base alla versione del sistema operativo. Ricordo che Windows Mobile 6.0 si basa sempre su Windows CE 5, per precisione sulla 5.2.

System.Data.Entities contiene invece le parti applicative dell'entitiy framework, mentre il provider è contenuto sotto System.Data.SqlServerCe.Entitiy.dll che arriva con l'installazione di Sql Server Compact Edition 3.5.

SQL CE 3.5 arriva con qualche piccola novità per i device e con grandi novità su utilizzato su desktop, Tablet o UMPC.

La directory di installazione sul pc di sviluppo è x:\program files\Microsoft SQL server Compact Edition\v3.5 e si presenta così:

 

Come accennato, entity framework viene reso disponibile tramite System.Data.SqlServerCe.Entity, ma solo se utilizzato su PC, Tablet o UMPC: non è quindi disponibile per Windows Mobile.

L'installazione prevede diversi componenti:

1) SSCEVSTools-ENU.msi: installa i componenti design-time in Orcas sotto la classica directory x:\program files\microsoft visual studio 9\Common7\IDE. Questi componenti non devono essere distribuiti

2) SSCERuntime-ENU.msi: installa i componenti di runtime per desktop, tablet e UMPC. Sono indispensabili sia a runtime che a design time. Questo MSI installa anche i nuovi componenti per la versione desktop di SQCE 3.5: Microsoft Synchronization Services for ADO.NET (OCS) e la già citata System.Data.SqlServerCe.Entity.dll.

3) SSCEDeviceRuntime.msi: installa i componenti destinati ai device e emulatori sulla macchina. Questi componenti sono necessari per l'integrazione con VS Orcas anche sulla macchina di sviluppo.

Le novità che abbiamo bollato come minori (rispetto appunto a EntityFramework e OCS) riguardano soprattutto il query processor :

- data type di tipo timestamp

- nested query

- CROSS apply e OUTER APPLY

- CAST

- TOP (finalmente !!!!!) diventa così più semplice paginare i dati per la loro visualizzazione nei minuscoli schermi

Oltre a OCS e Entity Framework, SQL CE 3.5, se utilizzato sul desktop, fornisce la possibilità di rientrare in una transazione creata con la System.Transaction 2.0: in due parole una operazione su SQL CE 3.5 può essere inserita all'interno del TransactionScope.

I Book On Line non sono ancora disponibili.

Abbiamo accennato nei post precedenti come in Visual Studio Orcas sia possibile effettura Unit Testing su device (o emulatore): credo che questa funzionalità, affiancata dal nuovo .NET CF RPM e dal profiler, siano le novità più importanti e utili della nuova versione.

Tra l'latro in Orcas gli strumenti di Unit Testing non sono più all'interno di Team System, ma disponibili nella versione Professional, almeno a quanto ci è dato sapere oggi.

Ecco le maschere di crezione di uno unit test, praticamente identiche (tranne un settaggio) a quanto oggi disponibile in VSTS:

 

 

 

Nella seconda immagine, come si può notare, la configurazione degli host prevede il tipo Smart Device con relativa piattaforma e scelta fra device e emulatore.

Se si crea una performance session su uno Unit Test il codice viene fatto girare sul desktop.

Anche senza l'automatismo in VS Orcas, oggi è possibile eseguire unit test su codice mobile, creando un progetto desktop con i sorgenti mobile linkati al suo interno e oppure compilazioni condizionali nel caso in cui il codice faccia uso di dispositivi, tipo lettore di codice a barre ad esempio, non disponibili sul desktop. Fra qualche giorno posso postare un mio articolo, scritto per Infomedia, proprio su questo argomento. La demo allegata all'articolo è già disponibile sul mio sito Think Mobile all'indirizzo http://thinkmobile.it/files/folders/mmdcii/entry5896.aspx.

Il nuovo Device Emulator 3.0 si presenta così:

 

 

A parte la user interface pressochè identica, è possibile salvare la configurazione degli emulatori con Save As e riconfigurare l'emulatore. Il file di configurazione (.defcfg) è anche molto semplice da modificare a mano per cambiare al volo qualcosa senza ricorre alla user interface e soprattutto per poter scambiare la configurazione degli emulatori fra i membri di un team di sviluppo senza doverla ricreare su ogni PC di sviluppo.

 

 

Dopo la nostra DevCon 2007 proseguiamo con SQL CE 3.5 e soprattutto con LINQ e WCF su mobile.

Alla prossima.

ASP.NET 2.0 Async Techniques

Articolo pubblicato su Computer Programming nel 2006.

Questo articolo, diviso in due parti unite in questo testo, introduce le problematiche di programmazione asincrona (e di conseguenza multithread) in ASP.NET, ripercorrendo passo per passo le modalità disponibili in ASP.NET 1.x per arrivare alle novità della versione 2.0. Il flusso, anche se con meno dettagli per questioni di spazio, ripercorre gli argomenti dei corsi www.devleap.it su ASP.NET 1.x e 2.0 Core. Per ogni demo, l'articolo contiene il codice relativo che potete copiare direttamente; all'indirizzo www.thinkmobile.it:9000/Async ho pubblicato tutti gli esempi funzionanti live in modo che possiate vedere e verificare il tutto su un server Windows 2003 già configurato: a sinistra trovate un menù che porta alle varie pagine riportate in questo articolo.

 

Quando si parla di programmazione asincrona facciamo riferimento all'esecuzione di operazioni su thread differenti, parallelizzando diverse richieste a risorse remote in modo da annullare il più possibile i tempi di attesa su ciascuna di esse: iniziare un articolo con un frase criptica solitamente incuriosisce il lettore :-)

Proviamo a spiegarci con alcuni esempi partendo da un client Windows (o mobile) tradizionale per poi spostarci su ASP.NET. Il mio obiettivo è chiarire e semplificare, il più possibile, concetti che esistono da sempre nello sviluppo di applicazioni e calarli piano piano nella realtà web che, come sempre, differisce dallo sviluppo di applicazioni tradizionali. Forniamo esempi molto semplici e facilmente riproducibili. In questo primo articolo ci dilungheremo un po' anche su IIS, Thread Pool e Asynchronous Thread Queue (ATQ) per inquadrare bene la problematica e dare al lettore elementi concreti di valutazione, piuttosto che segnalare solamente le carattestistiche di ASP.NET senza inquadrarle nello scenario complessivo.

 

Supponiamo di avere un client Windows che deve effettuare due chiamate a web service remoti per ottenere alcune informazioni. Utilizzeremo per praticità un solo web service il cui codice .NET 2.0 è il seguente.

 

---- SalesmanManagerWS.asmx ---

<%@ WebService Language="C#" CodeBehind="~/App_Code/SalesmanManagerWS.cs" Class="SalesmanManagerWS" %>

 

--- SalesmanManagerWS.asmx.cs ---

using System;

using System.Web;

using System.Web.Services;

using