Giunti a questo punto abbiamo la nostra app che serve per condividere i posti dove si mangia la vera focaccia genovese, dotata di gestioe della concorrenza e offline-sync.

Ora però occorre introdurre la possibilità di cancellare in modo corretto un item: più in dettaglio occorre introdurre un meccanismo che permetta a un record, scaricato in modalità offline da più dispositivi e successivamente cancellato da uno di questi che ne ha la facoltà, venga successivamente cancellato anche dal database locale degli altri client mobile coinvolti.

Al momento il meccanismo è questo: un record cancellato da un client viene rimosso al primo push anche sul database Sql Server: sincronizzazioni successive di altri dispositivi non vedranno alcuna traccia di tale record, e quindi lo lasceranno intonso nella propria base dati locale SqLite.

Occorre osservare che questa situazione secondo la logica esposta è assolutamente normale poichè si sta usando la sincronizzazione incrementale, e il record cancellato non viene riproposto in alcun modo nella fase di push incrementale (anzi proprio non esiste più..).

Quindi in una situazione come questa tutti gli altri dispositivi, all'infuori di quello che lo ha realmente cancellato, continueranno ad avere lo stesso record ben presente nella base dati.

Solo una sincronizzazione pull totale e non incremenatel (per esempio reinstallazione totale dell’applicativo, che cancella la base dati locale) non farà più comparire corretamente detto record.

Questa situazione in alcuni casi può essere perfettamente compatibile con le aspettative: in altre assolutamente no.

Per risolvere la situazione e proporre un comportamento più corretto, cioè che quando un record viene cancellato da un dispositivo, lo stesso poi dopo sia cancellato anche da tutti gli altri dispositivi alla prima sincronizzazione anche incrementale, occorre introdurre il soft delete.

Con questo meccanismo il record cancellato su un dispositivo in realtà alla sincronizzazione non viene cancellato su sql server, ma semplicemente viene marcato come tale usando il flag deleted Ucampo booleano) presente nella struttura dati.

Per introdurre la gestione del soft delete occorre modificare il backend agendo sul'Initialze del controller.

 public class FocaccePostController : TableController
    {
        protected override void Initialize(HttpControllerContext controllerContext)
        {
            base.Initialize(controllerContext);
            Focac_BookContext context = new Focac_BookContext();
            DomainManager = new EntityDomainManager(context, Request,true);
        }

Il terzo parametro posto a true indica che si intende attivare il soft delete.

Similmente anche nel modello del client occorre aggiungere questo campo.

public class FocaccePost
{
	public string Id { get; set; }

	[Microsoft.WindowsAzure.MobileServices.Version]
	public byte[] Version { get; set; }

	[Microsoft.WindowsAzure.MobileServices.UpdatedAt]
	public DateTimeOffset?  UpdatedAt { get; set; }

	[Microsoft.WindowsAzure.MobileServices.CreatedAt]
	public DateTimeOffset? CreatedAt { get; set; }

	[Microsoft.WindowsAzure.MobileServices.Deleted]
	public bool Deleted { get; set; }

	public string NomeUtente { get; set; }

	public string Luogo { get; set; }

	public DateTime DataOra { get; set; }

	public int Voto { get; set; }


}

In questo modo i record cancellati saranno denotati su Sql Server valorizzando il campo deleted a true: questo quindi sarà gestito come una normale modifica del record, e quindi di conseguenza il campo UpdatedAt sarà aggiornato alla data/ora attuale.

Oss.: Come visto in precedenza se la cancellazione avviene usando l'SDK il campo UpdatedAt viene automagicamente aggiornato: se invece viene gestito da un programma esterno allora sarà cura di quest'ultimo tenere aggiornato questo campo. L'utilizzo di un trigger come quello presentato nella puntata precedente leva ogni impaccio.

I client che eseguiranno il pull incrementale come visto in precedenza si vedranno arrivare questo record, ma siccome questo o è denotato dal flag deleted ecco al suo arrivo l'SDK saprà che dovrà cancellarlo dalla base dati locale SqLite, invece che eseguirne l'aggiornamento dei valori.

Solo dopo che si è sicuri che tutti i dispositivi avranno eseguito una sincronizzazione dei dati (pull incrementale), i record potranno quindi essere realmente cancellati per risparmiare spazio.

Nella pratica si possono eseguire delle operazioni di manutenzione automatica dell’istanza di Sql Server che dopo un tempo prestabilito cancella tutti i record marcati come deleted: in modo consistente a quanto visto sinora la data in cui il record è stato cancellato è memorizzato nel campo UpdatedAt, il cui valore può quindi essere utilizzato nel processo.

Linkografia

Git Page: Focac-Book in Xamarin