Alessandro Del Sole's Blog

{ A programming space about Microsoft® .NET® }
posts - 1902, comments - 2047, trackbacks - 352

My Links

News

Your host

This is me! Questo spazio è dedicato a Microsoft® .NET®, di cui sono molto appassionato :-)

Cookie e Privacy

Disabilita cookie ShinyStat

Microsoft MVP

My MVP Profile

Microsoft Certified Professional

Microsoft Specialist

Il mio libro su VB 2015!

Pre-ordina il mio libro su VB 2015 Pre-ordina il mio libro "Visual Basic 2015 Unleashed". Clicca sulla copertina per informazioni!

Il mio libro su WPF 4.5.1!

Clicca sulla copertina per informazioni! E' uscito il mio libro "Programmare con WPF 4.5.1". Clicca sulla copertina per informazioni!

These postings are provided 'AS IS' for entertainment purposes only with absolutely no warranty expressed or implied and confer no rights.
If you're not an Italian user, please visit my English blog

Le vostre visite

I'm a VB!

Guarda la mia intervista a Seattle

Follow me on Twitter!

Altri spazi

GitHub
I miei progetti open-source su GitHub

Article Categories

Archives

Post Categories

Image Galleries

Privacy Policy

Xamarin, Azure e il Visual Studio Mobile Center - Table e backend

Nel post precedente ho fatto un'introduzione del Visual Studio Mobile Center con una panoramica degli strumenti che offre. Avevamo iniziato creando un'app cross-platform con Xamarin, in cui avevamo attivato gli strumenti di analytics ma non avevamo fatto altro. Riprendiamo quindi il discorso parlando dei servizi di backend offerti dalle Tables, o Easy Tables nella terminologia di Azure, grazie alle quali possiamo avere delle tabelle in cui memorizzare dati nella Cloud.

Due note: ciò che si fa nel Visual Studio Mobile Center si fa anche nel portale di Azure, con la differenza che il Mobile Center semplifica enormemente le cose da fare; il portale di Azure torna comunque comodo per due aspetti, il primo relativo al fatto che le Tables usano SQLite ma per andare in produzione conviene mapparle a un database SQL Azure, cosa fattibile solo dal portale Azure, il secondo riguarderà poi l'autenticazione di cui parlerò tra due post.

Ciò premesso, andiamo nel Visual Studio Mobile Center e clicchiamo sul nome della nostra app. Infine, nel menu laterale click su Tables.

Creazione di una tabella
Nel post precedente vi ho accennato all'obiettivo da raggiungere, un'app che, in maniera chiaramente semplificata, gestisce un elenco di libri. Si tratta quindi di creare una tabella nella Cloud che memorizzi le informazioni tipiche di un libro come titolo, autore, ISBN, quantità e data di pubblicazione. Non includo il prezzo per una ragione: come vedrete tra breve, si utilizzerà JSON e serializzare un decimal richiede passaggi che "allungano troppo" il post e che rischiano di farci perdere il vero focus. Tenete a mente questo flash se vorrete farlo poi successivamente. Nella pagina del Mobile Center dovrete cliccare su un pulsante chiamato Create Table. A questo punto vi verrà richiesto di:

  • specificare un nome per la tabella. Chiamatela Book al singolare, per semplicità e per facile associazione al concetto di entity;
  • indicare se volete il soft delete, ossia evitare che un record venga eliminato fisicamente semplicemente marcandolo come eliminato ed escludendolo automaticamente dalle query. Selezionate questa opzione;
  • indicare se volete uno schema dinamico, che consentirà al servizio di generare le colonne sulla base dei dati che riceve; per il momento potete lasciarlo selezionato, se volete, ma deselezionatelo quando andate in produzione;
  • se volete che ogni utente abbia i propri dati. Questo farà sì che venga creata automaticamente una colonna chiamata userId sulla base della quale filtrare per utente. Ha senso in contesti di autenticazione, sia custom che tramite provider. La utilizzeremo tra due post, al momento deselezionatela.
Facendo click su Create, verrà creata una tabella con alcune colonne predefinite, più in particolare:

  • id, una stringa-Guid come identificativo del record.
  • deleted, un bool che indica se il record va marcato come eliminato o meno.
  • createdAt e updatedAt, due colonne data/ora che indicano la data e l'ora di creazione e modifica del record
  • version, che indica il numero di versione del record

Nota importante: il Mobile Center conosce solo 5 tipi di dato: Boolean, String, Number, Date e Version e quest'ultimo è usato solo dal sistema. Fate click su Edit Schema e poi su Add Column ripetutamente per aggiungere le seguenti colonne:

  • title, author, ISBN tutte e tre di tipo String;
  • publicationDate, di tipo Date;
  • quantity, di tipo Number.

Fondamentale: la nomenclatura non è casuale, il nome della colonna inizia con la lettera minuscola per poter piacere al formato JSON. Rispettatela!

Dopo aver salvato le modifiche, noterete che il Mobile Center vi fornisce un suggerimento su come referenziarla da codice:



Se avete già avuto esperienza con l'SDK di Azure per app client avrete familiarità, diversamente il suggerimento è poco utile. Niente paura, tra non molto vedremo cosa fare. Si tratterà, comunque, di scaricare l'Azure Mobile Client SDK per interagire da codice con le Table. I nostri dati sono chiaramente esposti in rete tramite un endpoint; per visualizzarlo, cliccate su Tables nel menu a sinistra, quindi sul nome della tabella per poterlo vedere come in figura:


Prendete nota di questo URL perché tra poco vi servirà.

Codice, model e un po' di architettura

Abbiamo la nostra tabella lato server nella Cloud, ora dobbiamo rappresentarla in codice C# con una classe che poi utilizzeremo per memorizzare e leggere i dati. Normalmente, il mio approccio nei post è quello di semplificare i progetti di esempio per consentirne una più facile comprensione anche a chi conosce meno determinati pattern come MVVM, ma questa volta non è così. Un minimo di architettura ci vuole per ottenere un risultato efficiente e soprattutto estendibile e riutilizzabile nei prossimi post (e anche per voi). Partiamo col dire che è necessario scaricare da NuGet la libreria chiamata Microsoft.Azure.Mobile.Client, da installare su tutti i progetti della solution (PCL, Android e iOS sicuramente). Questa si porta dietro Newtonsoft.Json come dipendenza, che utilizzeremo spesso. Vi faccio scaricare anche un altro pacchetto, il plugin chiamato Xam.Plugin.Connectivity, che consentirà di verificare la disponibilità di connettività direttamente dalla PCL.

Bisogna quindi creare una classe che rappresenti la nostra tabella. Ogni istanza di questa classe verrà serializzata in formato JSON e inviata alla Table dall'SDK di Azure. Il punto è che ogni tabella ha sempre delle colonne di sistema fisse, per cui l'idea è quella di partire da una classe astratta che chiamerò TableBase e che aggiungo in una cartella chiamata Model:

Notate come Version nella table sia mappato da un array byte[]. La classe implementa INotifyPropertyChanged affinché chiamanti come la UI possano aggiornarsi al variare dei dati. Notate come l'attributo JsonProperty consenta di mappare le proprietà .NET, con la relativa nomenclatura, alle colonne che hanno il nome aderente alla nomenclatura JSON. Altra nota importante: per i valori data/ora utilizzo DateTimeOffset invece che DateTime, perché i dati andranno a finire in SQLite (ora in Cloud ma la prossima volta anche in locale). SQLite ha un modo tutto suo di rappresentare le date e DateTimeOffset ci permette di rappresentare una data in formato UTC. Avendo una classe base, posso poi derivare più facilmente quelle che rappresentano un'entità specifica, come in questo caso Book che espone solo le proprietà caratteristiche di questo oggetto:

Fatto questo, definisco una classe statica che contiene una costante a rappresentare l'URL del mio servizio di backend:

Chiaramente, dovrete sostituire l'URL con quello del vostro servizio.

L'accesso ai dati

La comunicazione col servizio di backend avviene attraverso una classe chiamata MobileServiceClient dell'SDK di Azure. Questa classe va istanziata passando al costruttore l'URL del servizio. L'istanza, poi, offre una serie di metodi per lavorare coi dati: GetTable per ottenere un riferimento alla tabella, InsertAsync per aggiungere un oggetto, UpdateAsync per aggiornarlo, DeleteAsync per eliminarlo, ToListAsync/ToEnumerableAsync per ottenere elenchi anche tramite query filtrate. Sono tutti metodi generici, dove il type parameter è il tipo che mappa la tabella. In questo caso sarebbe Book. Dico sarebbe perché abbiamo creato una classe astratta, quindi a meno di esigenze specifiche, possiamo definire una classe che genericamente inserisca, aggiorni e carichi oggetti di tipo T. Se vi state chiedendo perché mi serve una classe apposita, è presto detto:

  • semplifico il salvataggio di un oggetto verificando che abbia bisogno di un insert o di un update
  • mi permette di verificare se c'è connettività in modo più organizzato
  • mi permette di migliorare la mia logica nelle query.

Ed eccola, una classe chiamata DataManager che metto in una cartella chiamata DataAccess:

Notate come la proprietà Id di ciascun oggetto venga utilizzata per capire se è da inserire o modificare. E' per questo che l'Id non viene generato in fase di istanza dell'oggetto. Ora capite perché questa classe è facilmente riutilizzabile, grazie ai generics e ai loro vincoli offre le stesse funzionalità a tutti gli oggetti che ereditano da TableBase. Un'istanza di questa classe serve a tutta l'applicazione, per cui la vado a mettere nella classe App:

A questo punto siamo pronti per definire il ViewModel.

Il ViewModel, con dati e comandi

Bisogna definire un ViewModel, che chiameremo BookViewModel e che creeremo in una cartella chiamata ViewModel. Il codice è abbastanza semplice: c'è una collection di Book che rappresenta l'elenco di dati, c'è un singolo Book a rappresentare l'elemento corrente, ci sono i vari command che richiamano i relativi metodi della classe DataManager. L'aggiunta e la rimozione, com'è ovvio, agiscono sulla collection.

La proprietà IsBusy ci servirà nella UI per il binding a un ActivityIndicator. Nota: a voler essere precisi, andrebbe gestito anche il CanExecute dei command. Per farlo conviene usare un'implementazione alternativa, ve la lascio come esercizio.

La User Interface

...che non sarà bellissima da vedere, ma fa quello che deve fare: lavorare in binding col ViewModel. Saprete poi voi come rendere la UI più gradevole o comunque più adatta alle vostre esigenze tramite apposite pagine e data template. Abbiamo quindi un ActivityIndicator per mostrare lo stato di "occupato", una ListView con un data template in binding con le varie proprietà dell'oggetto, alcuni pulsanti in binding coi vari command:

Da code behind, l'unica cosa che c'è da fare è istanziare il ViewModel e assegnarlo al context della pagina:

Test dell'app

A questo punto si va di F5 e si testa l'app nell'emulatore o su device fisico, come preferite. Vi ricordo che nel Mobile Center abbiamo aggiunto un'app per Android, ma gli stessi passaggi si possono fare anche per iOS.


La cosa interessante è che poi nel Mobile Center, accedendo alla nostra Table, saremo in grado di visualizzare l'elenco dei dati. Da li potranno essere eliminati oppure si potranno importare da file CSV. Si potrà anche gestire l'autorizzazione, ma lo faremo tra due post. Nel prossimo, invece, parleremo di sincronizzazione offline.

In sintesi, grazie al Mobile Center, siamo stati in grado di dotare la nostra app di un backend pronto all'uso nella Cloud con pochi passaggi e con la massima efficienza.

Alessandro

Print | posted on lunedì 13 febbraio 2017 00:00 | Filed Under [ Windows Azure and SQL Azure Xamarin ]

Powered by:
Powered By Subtext Powered By ASP.NET