El almacenamiento de datos de aplicación de Local y Roaming Storage con C#

Windows 8 tiene pocas maneras para almacenar datos de aplicación. La aplicación puede utilizar el directorio temporal para guardar cualquier tipo de información posible. Además WinRT proporciona soporte nativo para guardar datos en el almacén de datos de la aplicación como colección de pares de valor (Key-Value). Estos datos pueden ser almacenados localmente (Local o Temporary Storage) o utilizando un Roaming Storage. El Roaming Storage se sincroniza con Windows si el usuario permite la sincronización de datos (y cuando la sincronización esta permitida):

Para aprovechar las ventajas de este mecanismo la aplicación debe utilizar la clase ApplicationData del espacio de nombres Windows.Storage. Esta clase proporciona acceso a ambos, LocalSettings y RemoteSettings, que permiten abstraer la funcionalidad Guardar/Cargar desde la ubicación real de los datos.

En esta aplicación de ejemplo se trabajaran ambos tipos de almacenamiento. Como probablemente te acuerdas del post anterior, mi pantalla de configuración admite la conmutación entre tiendas activando o desactivando la sincronización de la configuración.

Independientemente a la ubicación de los datos reales (almacenamiento local o almacenamiento en la nube), la aplicación queda suscrita al evento DataChanged. Este evento se produce cuando el roaming de datos es sincronizado (en este ejemplo ocurre cuando se cambia en algún otro dispositivo que ejecuta la misma aplicación).

Nota: En este caso sincroniza sólo la configuración y, a continuación, vuelve a cargar los datos sincronizados una vez que fue modificado en otro dispositivo. En otros escenarios podría o no podría tener sentido la carga sincronizada de datos durante la ejecución de la aplicación y depende exclusivamente de la aplicación.

protected override void OnNavigatedTo(NavigationEventArgs e)

{
//Sunbscribe to DataChanged event to get notification if data changed in some other device
ApplicationData.Current.DataChanged += (sender, args) =>

{

//Reload settings when they changes somewhere

ReloadSettigns();

};

//Get settings

ReloadSettigns();

//…

}

Veamos en que consiste el método ReloadSettings:

private void ReloadSettigns()
{
    //Application logic prefers roaming storage over local one
    roamingSettings = ApplicationData.Current.RoamingSettings;
    if (roamingSettings.Values.Count == 0)
        roamingSettings = ApplicationData.Current.LocalSettings;
    //Application settings build from exactly 8 values. If something is missing use default values
    if (roamingSettings.Values.Count == 8)
    {
        //Value is object and must be cast to final type
        RemotePushEnabled = (bool)roamingSettings.Values["RemotePushEnabled"];
        LocationEnabled = (bool)roamingSettings.Values["LocationEnabled"];
        SensorsEnabled = (bool)roamingSettings.Values["SensorsEnabled"];
        LocalPushEnabled = (bool)roamingSettings.Values["LocalPushEnabled"];
        SharingEnabled = (bool)roamingSettings.Values["SharingEnabled"];
        ProximityEnabled = (bool)roamingSettings.Values["ProximityEnabled"];
        BackgroundAccess = (bool)roamingSettings.Values["BackgroundAccess"];
        SyncSettings = (bool)roamingSettings.Values["SyncSettings"];
    }
}

Se debe tener en cuenta que al cambiar algún valor en la pantalla de configuración, el valor se asigna a la variable correspondiente y el método SaveSettings es ejecutado:

private void SaveSettings()
{
    //Clean previous values
    CleanSettings();
    //If user prefers to sync data in the cloud use RoamingSettings, otherwise use LocalSettings
    if (SyncSettings)
        roamingSettings = ApplicationData.Current.RoamingSettings;
    else
        roamingSettings = ApplicationData.Current.LocalSettings;
    //Add values to settings
    roamingSettings.Values.Add("RemotePushEnabled", RemotePushEnabled);
    roamingSettings.Values.Add("LocationEnabled", LocationEnabled);
    roamingSettings.Values.Add("SensorsEnabled", SensorsEnabled);
    roamingSettings.Values.Add("LocalPushEnabled", LocalPushEnabled);
    roamingSettings.Values.Add("SharingEnabled", SharingEnabled);
    roamingSettings.Values.Add("ProximityEnabled", ProximityEnabled);
    roamingSettings.Values.Add("BackgroundAccess", BackgroundAccess);
    roamingSettings.Values.Add("SyncSettings", SyncSettings);
    //Signal data changed which will trigger cloud sync process when system synchronizes data next time
    ApplicationData.Current.SignalDataChanged();
}
private void CleanSettings()
{
    if (null != roamingSettings)
        roamingSettings.Values.Clear();
}

Nota: Limpiar todos los valores en lugar de sustituirlos no es probablemente la mejor práctica ya que puede aumentar el uso de tráfico en la sincronización, pero en el caso de éste simple ejemplo (y para mayor brevedad de código) se puede abordar de esta manera.

Por otra parte los ajustes pueden ser organizados en contenedores:

//Create new container
roamingSettings.CreateContainer("GeneralSettings", ApplicationDataCreateDisposition.Always);

//Setting named value in specific container
roamingSettings.Containers["GeneralSettings"].Values.Add("RegisteredUser", "AlexG");

//Getting named value form specific container
string user = (string)roamingSettings.Containers["GeneralSettings"].Values["RegisteredUser"];

//Delete container with all values
roamingSettings.DeleteContainer("GeneralSettings");

Cuando se utiliza la configuración de Roaming es importante saber cuántos datos se han sincronizado y cuántos podría ser sincronizados.
La clase ApplicationData proporciona información sobre la cuota de almacenamiento de roaming y su uso:
ulong quota = ApplicationData.Current.RoamingStorageQuota;
ulong used = ApplicationData.Current.RoamingStorageUsage;

Además, es posible crear la administración de la versión básica de datos almacenados en cualquier storage consultando la versión actual y la nueva configuración:

//Get current version
uint version = ApplicationData.Current.Version;
//Set new version
await ApplicationData.Current.SetVersionAsync(123, new ApplicationDataSetVersionHandler((version) => {
    if (version.CurrentVersion == version.DesiredVersion)
    {
         //Worked
    }
    else
    {
         //Something went wrong...
    }
}));

Por último, pero no menos importante, la clase ApplicationData proporciona acceso a las carpetas Local/Roaming/Temporary. Todas las clases exponen el API de muestra y permite administrar archivos y carpetas utilizando patrones de async de WinRT estándar:

//Create file in roaming folder. Also possible to create file/folder in ApplicationData.Current.TemporaryFolder or ApplicationData.Current.LocalFolder
StorageFile file = await ApplicationData.Current.RoamingFolder.CreateFileAsync("settings.dat", CreationCollisionOption.ReplaceExisting);//Open file for writing and write some binary buffer...
Stream stream = await file.OpenStreamForWriteAsync();
stream.Write(buffer, offset, count);
await stream.FlushAsync();

Traducido del post en inglés de Alex Golesh: Local and Roaming application data storage.

http://blogs.microsoft.co.il/blogs/alex_golesh/archive/2012/02/29/windows-8-consumer-preview-and-visual-studio-11-beta-local-and-roaming-application-data-storage-part-5-11.aspx

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Blog de WordPress.com.

Subir ↑

A %d blogueros les gusta esto: