Windows 7 Phone Database – Querying with Views and Filters
I’ve just added a feature to Rapid Repository to greatly improve how the Windows 7 Phone Database is queried for performance (This is in the trunk not in Release V1.0).
The main concept behind it is to create a View Model class which would have only the minimum data you need for a page.
This View Model is then stored and retrieved rather than the whole list of entities.
Another feature of the views is that they can be pre-filtered to even further improve performance when querying.
You can download the source from the Microsoft Codeplex site http://rapidrepository.codeplex.com/.
Setting up a view
Lets say you have an entity that stores lots of data about a game result for example:
- public class GameScore : IRapidEntity
- {
- public Guid Id { get; set; }
- public string GamerId {get;set;}
- public string Name { get; set; }
- public Double Score { get; set; }
- public Byte[] ThumbnailAvatar { get; set; }
- public DateTime DateAdded { get; set; }
- }
On your page you want to display a list of scores but you only want to display the score and the date added, you create a View Model for displaying just those properties.
- public class GameScoreView : IRapidView
- {
- public Guid Id { get; set; }
- public Double Score { get; set; }
- public DateTime DateAdded { get; set; }
- }
Now you have the view model, the first thing to do is set up the view at application start up.
This is done using the following syntax.
- public MainPage()
- {
- RapidRepository<GameScore>.AddView<GameScoreView>(x => new GameScoreView { DateAdded = x.DateAdded, Score = x.Score });
- }
As you can see, using a little bit of lambda syntax, you put in the code for constructing a single view, this is used internally for mapping an entity to a view.
*Note* you do not need to map the Id property, this is done automatically, a view model id will always be the same as it’s corresponding entity.
Adding Filters
One of the cool features of the view is that you can add filters to limit the amount of data stored in the view, this will dramatically improve performance.
You can add multiple filters using the fluent syntax if required.
In this example, lets say that you will only ever show the scores for the last 10 days, you could add a filter like the following:
- public MainPage()
- {
- RapidRepository<GameScore>.AddView<GameScoreView>(x => new GameScoreView { DateAdded = x.DateAdded, Score = x.Score })
- .AddFilter(x => x.DateAdded > DateTime.Now.AddDays(-10));
- }
If you wanted to further limit the data, you could also say only scores above 100:
- public MainPage()
- {
- RapidRepository<GameScore>.AddView<GameScoreView>(x => new GameScoreView { DateAdded = x.DateAdded, Score = x.Score })
- .AddFilter(x => x.DateAdded > DateTime.Now.AddDays(-10))
- .AddFilter(x => x.Score > 100);
- }
Querying the view model
So the important part is how to query the data.
This is done using the repository, there is a method called Query which accepts the type of view as a generic parameter (you can have multiple View Model types per entity type)
You can either use the result of the query method directly or perform further querying on the result is required.
- public void DisplayScores()
- {
- RapidRepository<GameScore> repository = new RapidRepository<GameScore>();
- List<GameScoreView> scores = repository.Query<GameScoreView>();
- // display logic
- }
- public void TodaysScores()
- {
- RapidRepository<GameScore> repository = new RapidRepository<GameScore>();
- List<GameScoreView> todaysScores = repository.Query<GameScoreView>().Where(x => x.DateAdded > DateTime.Now.AddDays(-1)).ToList();
- // display logic
- }
Retrieving the actual entity
Retrieving the actual entity can be done easily by using the GetById method on the repository.
Say for example you allow the user to click on a specific score to get further information, you can use the Id populated in the returned View Model GameScoreView and use it directly on the repository to retrieve the full entity.
- public void GetFullEntity(Guid gameScoreViewId)
- {
- RapidRepository<GameScore> repository = new RapidRepository<GameScore>();
- GameScore fullEntity = repository.GetById(gameScoreViewId);
- // display logic
- }
Synchronising The View
If you are upgrading from Rapid Repository V1.0 and are likely to have data in the repository already, you will need to perform a synchronisation to ensure the views and entities are fully in sync.
You can either do this as a one off during the application upgrade or if you are a little more cautious, you could run this at each application start up.
- public void MyUpgradeTasks()
- {
- RapidRepository<GameScore>.SynchroniseView<GameScoreView>();
- }
It’s worth noting that in normal operation, the view keeps itself in sync with the entities so this is only really required if you are upgrading from V1.0 to V2.0 when it gets released shortly.
Summary
I really hope you like this feature, it will be great for performance and I believe supports good practice by promoting the use of View Models for specific pages.
I’m hoping to produce a beta for this over the next few days, I just want to add some more tests and hopefully iron out any bugs.
I would really appreciate any thoughts on this feature and would really love to know of any bugs you find.
You can download the source from the following : http://rapidrepository.codeplex.com/
Kind Regards,
Sean McAlinden.