Architecting WP7 - Part 4 of 10: Client-side Data

  • Oct 14, 2010 at 4:27 PM
  • Shawn Wildermuth
  • 3 Comments

Windows Phone 7

In this fourth part of my Architecting Windows Phone 7 series, I will tackle client-side data. If you've missed the past parts of the series, you you can visit them here:

One of the main complaints about Silverlight on the phone (especially to WinMo veterans) is the lack of a local database store. But being able to store data is still really possible, it is just that any data you store locally is not necessarily in a database format.  But maybe that doesn't matter as much as you might expect.

 While not having an on-disk relational store is a limitation, depending on the size of your data, you can do quite a lot without one. In my "Stay Glucose to Me" application, I decided to just store the data on disk. In a 1.1 version, I am going to support a multi-file approach so that it only keeps the last 3 months in memory, but for now it just stores it all as a single file. This file is married to my Model like so:

public class GlucoseModel
{
  private const string READINGSFILE = "readings.xml";

  // ...
  
  User ReadUser()
  {
    User user = null;

    using (var store = 
      IsolatedStorageFile.GetUserStoreForApplication())
    {
      if (store.FileExists(READINGSFILE))
      {
        using (var file = store.OpenFile(READINGSFILE, FileMode.Open))
        {
          var writer = new XmlSerializer(typeof(User));
          var result = writer.Deserialize(file);
          user = result as User;
        }
      }

      if (user == null)
      {
        user = new User();
      }
    }

    return user;
  }

  public void SaveUser(User user)
  {
    using (var store = 
      IsolatedStorageFile.GetUserStoreForApplication())
    using (var file = store.CreateFile(READINGSFILE))
    {
      var writer = new XmlSerializer(typeof(User));
      writer.Serialize(file, user);
      file.Flush();
      file.Close();
    }
  }

}

I am using simple XML Serialization to store the data. I thought about doing JSON instead for size on disk, but ran into some bugs so switched to XML Serialization. Note that I am using Isolated Storage for the data. In my case, I am saving the data as it changes so that I never have to worry about tombstoning. This does imply that I am loading all the data on load.  Long-term this won't work in my case, but depending on your app, this isn't hard to fix with multiple files. 

Two issues come up with this strategy: serialization and querying. I am mixing my data objects with some temporary data (StartDate and EndDate). These properties are used to determine what data to show and shouldn't be serialized (or in some cases can't be serialized).

public class User : ObservableObject // Implements INPC for me
{
  public User()
  {
    Readings = new ObservableCollection();
  }

  string _name = "";
  public string Name
  {
    get { return _name; }
    set
    {
      _name = value;
      RaisePropertyChanged("Name");
    }
  }

  // ...

  ObservableCollection _readings;
  public ObservableCollection Readings
  {
    get { return _readings; }
    private set
    {
      _readings = value;
      RaisePropertyChanged("Readings");
    }
  }

  [XmlIgnore]
  public DateTime StartDate
  {
    get { return DateTime.Now.AddDays(-21); }
  }

  [XmlIgnore]
  public DateTime EndDate
  {
    get { return DateTime.Now; }
  }

}

In my case I wanted to omit them from my serialization so using the XmlIgnore attribute did the trick. So controlling serialization is something you may want to implement (depending on your data of course).

The second issue is querying. This is a lot trickier. With my initial approach of load *all* the data, I can just use LINQ:

var qry = from r in _theUser.Readings
          where r.ReadingDateTime >= App.ViewModel.CurrentUser.StartDate
          group r by r.ReadingDateTime.Date into dayGroup
          select new ReadingDay
          {
            Date = dayGroup.Key,
            Value = dayGroup.Average(r => r.Value)
          };

But constructing these sorts of queries without loading all the data is a definite problem with client-side data. I don't have an answer.  But if you are just using the client-side data as a cache, complex queries could be done at the server (e.g. WCF, OData, etc.).

The important part of this story is that you can accomplish a lot without resorting to a client-side database, but there are limitations. I know there are a few WP7 compatible in-memory databases but I haven't looked at them or their memory footprint yet. With the size considerations of data in WP7, I don't see how most projects would need this. It will be awesome when we get it, but you can certainly work around it.

 

 

Comments

Gravatar

Geoff Friday, October 15, 2010

I've been using the below "unofficial" sqlite w/o problems so far. I haven't done extensive testing but I'm reading from a DB of all US rivers and I haven't gone above 30 MB. Speed has been acceptable (no device yet though) but generally I'm filtered by state and am not dealing with more than a few hundred records at a time.

http://sviluppomobile.blogspot.com/2010/09/wp7-deploy-db-as-content-file.html

Gravatar

Julio Trujillo Leon Wednesday, October 20, 2010

I disagree completely with Shawn. The local database is full and absolutely necessary. The typical usage scenario is that of a company staff displaced on route ie. route workers interlinking who need access to information for consultation and store ie. orders. If a path point no connection with the operator of mobile, then, how do query information relating to that point or store it?
3G coverage maps, GPRS operators can be seen plenty of "gaps" or tracts of land where the phone will be offline. On those sites WPhone 7 would be unusable for use by needing to work consume data via WCF Apps.

Gravatar

Shawn Wildermuth Wednesday, October 20, 2010

Julio,

No, I don't think its absoutely necessary...especially in this release which is consumer focused. I would guess you're a Windows Mobile enterprise developer. I say that because you're used to having a local db and writing apps that use the phone as a non-consumer device. You need it. No question. But for the majority of apps, I think we can live without it this initial release.

Its a matter of priorities. To say they should have held back WP7 because of that limitation would be wrong. Lots of gaps in coverage mean that lots of apps (regardless of what type) would not work while offline. That's the nature of today's phone apps.


Leave a Comment

*
*
*