Restoring the local database
involves submitting a background transfer request to download the
previously uploaded file from the server. The file is downloaded to a
temporary location in isolated storage, the existing local database is
disconnected, and its file is replaced.
The RestoreDatabase
method begins by creating a temporary directory where the downloaded .sdf file can be placed by the BackgroundTransferService
:
const string downloadPath = transferDirectory + "/" + localDatabaseName;
using (IsolatedStorageFile isolatedStorageFile
= IsolatedStorageFile.GetUserStoreForApplication())
{
if (!isolatedStorageFile.DirectoryExists(transferDirectory))
{
isolatedStorageFile.CreateDirectory(transferDirectory);
}
}
It then creates two Uri
objects specifying the location of the .sdf file on the remote server,
and the file’s destination location in isolated storage, as shown:
string deviceId = GetUserId();
string remoteUrl = string.Format("{0}{1}_{2}",
downloadUrl,
deviceId,
localDatabaseName);
Uri remoteUri = new Uri(remoteUrl, UriKind.Absolute);
Uri localUri = new Uri(downloadPath, UriKind.Relative);
The BackgroundTransferRequest
is constructed using the two Uri
objects. The default HTTP method Get is used because we are downloading the file to the device. See the following excerpt:
BackgroundTransferRequest request
= new BackgroundTransferRequest(remoteUri, localUri)
{
TransferPreferences = TransferPreferences.AllowBattery,
};
Finally, we subscribe to the transfer request’s status changed and progress changed events, and the request is added to the BackgroundTransferService
. The progress indicator is displayed, and it is updated as the progress of the background transfer changes:
request.TransferStatusChanged += HandleDownloadTransferStatusChanged;
request.TransferProgressChanged += HandleDownloadTransferProgressChanged;
BackgroundTransferService.Add(request);
Message = "Restoring data from cloud.";
Progress = 0;
ProgressVisible = true;
When the background transfer completes, the TransferStatusChanged
event handler is called (see Listing 1). The downloaded file is copied to the location of the local database, which replaces the existing file. The ITodoService.Initialize
method re-creates the connection to the database, and the viewmodel’s GroupedTodoItems
are re-created via a call to PopulateItems
.
LISTING 1. HandleDownloadTransferStatusChanged
Method
void HandleDownloadTransferStatusChanged(object sender,
BackgroundTransferEventArgs e)
{
if (e.Request.TransferStatus == TransferStatus.Completed)
{
BackgroundTransferService.Remove(e.Request);
ProgressVisible = false;
if (e.Request.TransferError != null)
{
MessageService.ShowError("An error occured during restore.");
return;
}
try
{
using (IsolatedStorageFile isolatedStorageFile
= IsolatedStorageFile.GetUserStoreForApplication())
{
string downloadedFile
= e.Request.DownloadLocation.OriginalString;
isolatedStorageFile.CopyFile(downloadedFile,
localDatabaseName, true);
}
todoService.Initialize();
ClearPinnedItems();
PopulateItems();
}
catch (Exception ex)
{
MessageService.ShowError("An error occured during restore.");
return;
}
MessageService.ShowMessage("Restore successful.");
}
}
Backup and restore operations are actuated by application bar menu items in the view. The view’s AppBar
menu items are bound to the BackupDatabaseCommand
and the RestoreDatabaseCommand
(see Figure 1).
FIGURE 1 The TodoListView
provides menu items for backing up and restoring the local database,
and a progress indicator that shows the progress of the background
transfer request.
Using a BackgroundTransferRequest
is an effective way to back up your apps’ data because it does not rely
on your foreground app being active. Be mindful, however, that the BackgroundTransferService
does not guarantee that a transfer request will be serviced.