Join Scott Peterson for an in-depth discussion in this video Working with Azure Table Storage, part of Developing UWP Apps: 8 Cloud and Connected Services.
- [Instructor] We're over in visual studio 2017 and in our UWP tagger app we've been working on in the series to take a look at how it might make sense to add table storage to our app. So let's just do a quick refresher on where we're at in this series. We've added quite a bit of functionality in the previous sessions related to navigational layout commands, push notifications, printing, audio and video effects.
Quite a wide variety of features and services that are available in universal windows platform and I though it might make sense since we have all these great images that we're working with and all of this image analysis if we might introduce the concept of favorites. And so thought it might be a good idea for each one of these images if we added the ability to favorite and unfavorite an image. But as you know, this data right now is only temporary storage, table storage might be a good place to just store these favorites.
This way we can easily have this favorite data available everywhere. And so this is a really goo fit for azure table storage because we have some simplified data, we don't really need a lot of relationships. So why don't we go ahead and add a button here in our control that would handle toggling favorites. So let's go ahead and close that and open up the image control we created in the advanced control session.
And we'll just scroll down here right above this progress grid, let's go ahead and add this grid, take a look at it. So I got a grid that's going to be aligned top right on the control and I've got an ellipse as a background and I've essentially just made this ellipse black and it's just going to be 40 by 40. And this makes it easy for a favorite icon to show up regardless of what the image colors contain.
Then on top of that I've just added another app bar button and we're binding the opacity of the app bar to new property I've created on our image info class called is favorite. And I've created a converter; is favorite opacity converter and essentially what this will do, is if it's a favorite it'll have an opacity of 1.0, if it is not a favorite it will essentially be slightly transparent. So yet opacity will be changed on that.
But now I've added a command to get call to toggle whether this is a favorite or not. So I'm passing the image info over the command parameter and the command is going to be pointing to toggle is favorite commands. Let's take a look at that toggle is favorite command and right now we can see it's essentially doing nothing. So let's load this up to see how this might look in our app.
We've got this black ellipse, essentially this circle that has a dimmed out favorites icon, we can just click on that icon and just going to send this over to our command. So one quick way that we can just toggle that is just to say parameter as image info.IsFavorite equals not IsFavorite. So let's look that up again and so remember we're using this an observable binding here.
So now as we click we see how it toggles the opacity easily of that favorite. But it's actually doing nothing here and this is just kind of a meaningless visual here, let's add some code that might make more sense. But before we do that, let's look at table storage, the table destroyed that we've set up. So if I go over her to the Azure portal, we'll see that I've created a storage account that I've called tagger and I've got zero blogs, zero files, zero tables nothing is created here.
If I go to tables we see that we've got nothing there yet. Let's throw this data in the table storage see how we might create some code to do that. So I've created this helper called table storage helper, let's add a couple methods here and see what this code might look like. So the first method I'm going to pull in is this get favorites table A sequence, let's take a look at what we're doing. The first thing we're going to do is initiate the storage account connection, so I'm going to say cloud storage account equals new, cloud storage and I'm just passing at a string of cloud storage connection string.
Let me show you where we're going to grab that. If we go over to the portal, we go to access keys, now remember I mentioned there's a couple different ways we can manage this permission; we can setup a shared access signature and make this time based and generate the SAS here or we could simply say this is going to be at the service level and just get an access key for it but also a connection string. So if I pull that view connection string notice I've got a connection string here.
So I'm just going to use this connection string as our connection string to the storage. Now remember this is just going to the entire storage account itself not necessarily tables but just to the entire storage account. And then I'm going to spin up a table client by using create cloud table client and then I'm going to get a table reference and we're going to call this table favorites and then I'm going to call create if not exist a sync and then I'm going to return the table. So this is helpful because that way it's either going to create or return it, one or the other and then we got a nice table object we can work with.
But what about adding data? So I've also created this method, this fairly simple method called add favorite a sync. So first I'm going to call that get favorite table method, it's just going to basically make sure we have a favorites and connect to that storage account and then I'm going to spin up a new favorite object and this is an object I created. Let's go over an take a look at that, if I go to definition notice I've got this class called favorite and I'm just inheriting from the table entity object from storage.table.tableentity and then I'm setting the partition key in row key this is very similar to what you do in document db.
It's not necessarily what you do with a standard sequel server or relational database scenario. And we don't have to set these but this is very helpful to set these, the partition key in row key. I'm going to set the partition key as the file name and row key is the file extension and then I've just got these properties on the class; file name title, file extension and whether it is video content. So basically I'm just newing up a new favorite, I'm setting the title, the file name and whether it's video content and then I'm calling insert or replace.
This is similar to an upsert an insert update; an upsert and then I'm calling it execute a sync, passing that operation. So if we go back over our command we can update this code, I'm going to add this method in here, start toggle favorite a sync and instead of just toggling it there, I'm going to say parameter as image info and I'm just going to call this method.
So you remember from our commands and converters session that we're just calling this command, we're setting these properties on our view model, so I'm saying is busy and now I'm toggling the favorite here and I'm saying if it is a favorite add it to favorites, if I defavorite it or unfavorite it, remove the favorite. So let's go over to that helper class and let's add a couple more of these methods and take a look at how we would remove that favorite.
So essentially what we're doing is we're removing it from table storage. So if we were to work against mobile services or standard sequel server this would be similar to just saying delete, delete where, delete star, delete where, it equals this image. But for table storage we're just getting reference to the table and now I'm getting reference to the specific favorite based on that image. So let's go to that method. So to get a single favorite I'm doing now a retrieve operation and notice how I'm passing that class.
This gives us the ability to have a scheme list or loosely typed schemes to retrieve objects. So I'm saying retrieve something that matches that class definition of favorite and then I'm passing at the properties I used for a partition key in row key which were a file name and the file extension and then I'm saying execute a sync just going to do a retrieve and return the result. So now I have a reference to the table object, I now have a reference to the specific favorite that's been added and now I'm just doing a delete operation.
So instead of doing the insert and update I'm just doing a delete and passing the favorite and executing a sync. So that should work pretty good. You see how clean this is, basically I'm just saying; table operation delete, I could say table operation insert or merge or replace, retrieve, whatever I need to do its just clean and strongly typed. So let's go back to our command and just confirm here. So when the user clicks a button to toggle the favorite, I'm going to pass it to this method and I'm just going to toggle that is favorite value.
So if it's true it's going to be false false it's going to be true and I'm going to say if it is a favorite add it if it's not going to be a favorite remove it. So we'll jus go ahead and put a break point there and a break point here, might as well just throw it in here and let's see how that might look. So remember in the portal, we don't have any tables created yet. This makes it really easy for us just to create a table if there is not one and not even worried about setting up columns or fields or data types or anything like that.
So let's go ahead and run that see how that might look. So let's just go ahead and tag this one. Great, man smiling at the camera let's go ahead and favorite that. It is a favorite now, so just going to go ahead and go to that method. We'll put just a couple of break points here and notice that it's bringing back a table object, we're going to spin up a new favorite, so if we take a look at that favorite, notice how it gets populated with all the information that matters and then we're going to do an execute a sync on that insert operation and now that's been added as a favorite.
Now if we go over to the Azure portal notice how we have this favorites table that's been created for us and has the content there and when we get to our section on storage explorer we can take a look at that but extremely simple and then of course if we remove it its now is favorite equal false. We can step through that code we can see that we have the favorite we're passing the entire favorite object over to the delete operation in then performing a delete.
So extremely simple to manage that using table storage but table storage is fairly crummy at storing binary data. As you recall throughout this entire series, we've kind of bee working against temporary storage, local storage in our app storage and just continuing to put all this stuff in temporary storage. We could maybe throw this in roaming storage or things like that. But having large objects in roaming storage is pretty crummy too because we've got that latency issue.
It would be nice to be able to grab all of this data across devices by leveraging some type of centralized redundant storage external to the app. So table storage is great for this kind of data like whether it's a favorite or not but it doesn't do a good job when it comes to bytes or byte rays or streams or ac techs or large objects like that. So why don't we flip back over to the slide deck and see how maybe we could use a different type of cloud service that as your blob storage to make this a little bit more full featured and migrate the code that stores it in temporary storage over using blob storage.
Note: This course was created by Wintellect. We are pleased to host this training in our library.