Search code examples
c#windows-phone-8windows-phone-8.1xamarin.forms

How to handle prepopulated database in Windows Phone 8.1


I need to use a prepopulated database in my Xamarin.Forms application, so I searched for possible solutions.

I've found this article and tested with Android - it worked okay.

However, it uses Windows Phone 8 - that is not compatible with Windows 8.1.

So I tried to modify this Windows Phone 8 code:

public static void CopyDatabaseIfNotExists(string dbPath)
{
  var storageFile = IsolatedStorageFile.GetUserStoreForApplication();

  if (!storageFile.FileExists(dbPath))
  {
    using (var resourceStream = Application.GetResourceStream(new Uri("people.db3", UriKind.Relative)).Stream)
    {
      using (var fileStream = storageFile.CreateFile(dbPath))
      {
        byte[] readBuffer = new byte[4096];
        int bytes = -1;

        while ((bytes = resourceStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
        {
          fileStream.Write(readBuffer, 0, bytes);
        }
      }
    }
  }
}

Into this code:

public static async void CopyDatabaseIfNotExists(string dbPath)
{
  IStorageFolder applicationFolder = ApplicationData.Current.LocalFolder;

  StorageFile existingFile = await Windows.Storage.StorageFile.GetFileFromPathAsync("prep.db");
  IStorageFile storageFile = await applicationFolder.GetFileAsync(dbPath);

  if (storageFile == null)
  {
    await existingFile.CopyAndReplaceAsync(storageFile);

However, it does not work, I can't provide a proper filepath for my existing db file (it is in the root of the project), it always gives me this error:

Value does not fall within the expected range.

How could I get a proper path to my prepopulated file?

Also, why do I need to use a stream based "copy" when I could simply copy the file itself?


Solution

  • The following code works for Windows Phone 8.1 and UWP:

    public async void CopyDatabaseIfNotExists(string dbPath)
    {
      IStorageFolder applicationFolder = ApplicationData.Current.LocalFolder;
      var existingFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(myDBFileName);
    
      if (!await CheckForExistingFile(myDBFileName))
        await existingFile.CopyAsync(applicationFolder);
    }
    
    private async Task<bool> CheckForExistingFile(string filePath)
    {
      try
      {
        var file = await ApplicationData.Current.LocalFolder.GetFileAsync(Uri.EscapeDataString(filePath));
        //no exception means file exists
        return true;
      }
      catch (FileNotFoundException ex)
      {
        //find out through exception
        return false;
      }
    }