Azure Storage - krzysiek861/AvanadeWorkshop GitHub Wiki
This step is obligatory!
git checkout feature/azure-storage
If you experience any issues with checking this branch out first stash all the changes you have from previous modules, checkout the branch and then apply the changes back.
Add Azure.Data.Tables NuGet to WebApp project.
Open Models/Table Storage Models
folder in WebApp and add following classes:
public class TeamEntity : ITableEntity
{
public TeamEntity()
{
}
public TeamEntity(string partition, string id)
{
PartitionKey = partition;
RowKey = id;
}
public string Group { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public string Flag { get; set; }
public int Games { get; set; }
public int Points { get; set; }
public string PartitionKey { get; set; }
public string RowKey { get; set; }
public DateTimeOffset? Timestamp { get; set; }
public ETag ETag { get; set; }
}
public class PlayerEntity : ITableEntity
{
public PlayerEntity()
{
}
public PlayerEntity(string teamId, string id)
{
PartitionKey = teamId;
RowKey = id;
}
public string TeamId { get { return PartitionKey; } }
public int? Number { get; set; }
public string Position { get; set; }
public string FullName { get; set; }
public DateTime DateOfBirth { get; set; }
public string Club { get; set; }
public int Goals { get; set; }
public string Thumbnail { get; set; }
public string PartitionKey { get; set; }
public string RowKey { get; set; }
public DateTimeOffset? Timestamp { get; set; }
public ETag ETag { get; set; }
}
Open DevController and modify MapPlayer
and MapTeam
methods replacing dynamic
as a return value with PlayerEntity
and TeamEntity
private PlayerEntity MapPlayer(Player player)
{
return new PlayerEntity(player.TeamId, Guid.NewGuid().ToString())
{
Club = player.Club,
DateOfBirth = player.DateOfBirth,
Number = player.Number,
Position = player.Position,
FullName = player.FullName
};
}
private TeamEntity MapTeam(Team team)
{
return new TeamEntity(2022.ToString(), team.Name.Replace(" ", ""))
{
Flag = team.Flag,
Name = team.Name,
Group = team.Group.ToString()
};
}
Open TeamsRepository
, implement StoreTeams
and StorePlayers
methods:
public async Task StoreTeams(IEnumerable<TeamEntity> teams)
{
var tableClient = GetServiceClient();
var table = tableClient.GetTableClient("teams");
await table.CreateIfNotExistsAsync();
var transactionActions = new List<TableTransactionAction>();
foreach (var team in teams)
{
transactionActions.Add(new TableTransactionAction(TableTransactionActionType.UpdateReplace, team));
}
await table.SubmitTransactionAsync(transactionActions);
}
public async Task StorePlayers(IEnumerable<PlayerEntity> players)
{
var tableClient = GetServiceClient();
var table = tableClient.GetTableClient("players");
await table.CreateIfNotExistsAsync();
foreach (var group in players.GroupBy(p => p.PartitionKey))
{
var transactionActions = new List<TableTransactionAction>();
foreach (var player in group)
{
transactionActions.Add(new TableTransactionAction(TableTransactionActionType.Add, player));
}
await table.SubmitTransactionAsync(transactionActions);
}
}
Deploy your Web app to Azure. Enter /Dev url and click Fill Azure Table Storage
. Note: opening /Home controller at this stage will result in errors as some of the methods are not implemented yet.
Important! Do not click the link more than once otherwise it will result in duplicates.
Download Azure Storage Explorer (link) and log in using your Azure account credentials.
Expan tables and browse the data. Try to find:
- all the teams from group H
- all the players with number 10
- all the players under 20
Make sure to restore all Nuget Packages
Open TeamsRepository.cs
and implement two missing methods:
public IEnumerable<TeamEntity> FetchTeams()
{
var tableClient = GetServiceClient();
var table = tableClient.GetTableClient("teams");
return table.Query<TeamEntity>().OrderBy(f => f.Group);
}
public IEnumerable<PlayerEntity> FetchPlayers(string teamId)
{
var tableClient = GetServiceClient();
var table = tableClient.GetTableClient("players");
var result = table.Query<PlayerEntity>(p => p.PartitionKey == teamId).OrderBy(f => f.Number);
return result;
}
Deploy your Web App.
Run the application and observe the data flow.
Open PlayersService.cs
and analyze GetPlayerImages
method. Try to implement all empty methods used there.
Open BinaryFilesRepository
and add following method:
private BlobServiceClient GetBlobserviceClient()
{
var serviceClient = new BlobServiceClient(GlobalSecrets.StorageAccountConnectionString);
return serviceClient;
}
Implement SaveBlob
method:
public string SaveBlob(string containerName, string fileName, byte[] bytes)
{
var serviceClient = GetBlobserviceClient();
var container = $"{containerName}-{fileName}".ToLower();
var blobContainerClient = serviceClient.GetBlobContainerClient(container);
blobContainerClient.CreateIfNotExists();
blobContainerClient.SetAccessPolicy(Azure.Storage.Blobs.Models.PublicAccessType.Blob);
var blobClient = blobContainerClient.GetBlobClient(Guid.NewGuid().ToString() + ".png");
using (var stream = new MemoryStream(bytes, writable: false))
{
blobClient.Upload(stream);
return blobClient.Uri.AbsoluteUri;
}
}
Try to run the application and open few player profiles. Open Storage Explorer. Locate your blobs. Click on Properties tab. Copy the URL and try to open it in the browser.
Implement missing repository methods:
public bool AnyFileExists(string containerName, string fileName)
{
var serviceClient = GetBlobserviceClient();
var container = $"{containerName}-{fileName}".ToLower();
var blobContainerClient = serviceClient.GetBlobContainerClient(container);
return blobContainerClient.Exists();
}
public List<string> GetBlobUrls(string containerName, string fileName)
{
var serviceClient = GetBlobserviceClient();
var container = $"{containerName}-{fileName}".ToLower();
var blobContainerClient = serviceClient.GetBlobContainerClient(container);
return blobContainerClient.GetBlobs()
.Select(b => blobContainerClient.GetBlobClient(b.Name).Uri.ToString())
.ToList();
}
Open Azure Portal and browse Storage account metrics.