Back - Azure > Azure Storage
The Requirement
Assuming that we already completed the 1.1 Create/Add Azure Table Storage Entity and 1.2 Get All Entities In Azure Table, We are now ready to refactor our simple CRUD operation in a single .dll file that we may reference in our Middle Tier ( Web Api ).
Consideration
This code base is proposed for the intention for understanding its usage, for production/release we might need to tweak it to meet the company policy, best practice and industry standards.
Refactor The Account Setup
In the previous implementations, we saw some repeatable code that we may refactor, We start by refactoringg the CloudStorageAccount instantiation in a static class.In the proposed code below, we also introduce an overload for the SetupAccount method , this will allow the reference library open for dynamic variables that may be used in the Middle tier ( in this case, Asp.Net Web API ).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.WindowsAzure.Storage; | |
namespace CrudAzureTablseStorage | |
{ | |
public static class AzureSettings | |
{ | |
// Overload For Clients Implementations | |
public static CloudStorageAccount SetupAccount(string AccountName, string AccountKey) | |
{ | |
Microsoft.WindowsAzure.Storage.Auth.StorageCredentials cred = | |
new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials( | |
AccountName, | |
AccountKey | |
); | |
CloudStorageAccount acc = new CloudStorageAccount(cred, AccountName, StorageSettings.EndPointSuffix, true); | |
return acc; | |
} | |
// Overload For Dev Settings | |
// May be used for Productions too , Provided that the policy allow to Hard Code Details in the .dll | |
// The best practice is to use Azure AD(Cloud)/AD(OnPrem)/RBAC alongside with Key Vault(Cloud) | |
public static CloudStorageAccount SetupAccount(bool IsLive) | |
{ | |
Microsoft.WindowsAzure.Storage.Auth.StorageCredentials cred = | |
new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials( | |
StorageSettings.AzureStorageAccountName(IsLive), | |
StorageSettings.AzureStorageKey(IsLive) | |
); | |
CloudStorageAccount acc = new CloudStorageAccount(cred, StorageSettings.AzureStorageAccountName(IsLive), StorageSettings.EndPointSuffix, true); | |
return acc; | |
} | |
} | |
internal static class StorageSettings | |
{ | |
public static string AzureStorageAccountName(bool IsLive) | |
{ | |
if(IsLive) | |
return "LiveDataAzureStorageTableName"; | |
else | |
return "DevAzureStorageTableName"; | |
} | |
public static string AzureStorageKey(bool IsLive) | |
{ | |
if(IsLive) | |
return "LiveKey"; | |
else | |
return "DevKey"; | |
} | |
public static string EndPointSuffix { get { return "core.windows.net"; } } | |
} | |
} |
Refactor The Add Operation Helper
In our code below only 2 methods that are accessible to the clients who referenced this .dll, The AppOperation method access modifier is decorated with internal which protect it from being used by other assemblies.We also decorated the Add.New method with overload for dynamic configuration at the client side.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using Microsoft.WindowsAzure.Storage; | |
using Microsoft.WindowsAzure.Storage.Table; | |
namespace CloudAzureTableseStorage | |
{ | |
public static class Add | |
{ | |
// Overload For Dev Settings | |
public static bool New(string TableName, ITableEntity DataModel,bool IsLive) | |
{ | |
if(IsLive != null) | |
CloudStorageAccount sa = AzureSettings.SetupAccount(IsLive); | |
else | |
CloudStorageAccount sa = AzureSettings.SetupAccount(false); | |
return AddOperation(TableName,DataModel,sa); | |
} | |
// Overload For Live/Production Settings | |
public static bool New(string TableName, ITableEntity DataModel,string AccName , string AccKey) | |
{ | |
CloudStorageAccount sa = AzureSettings.SetupAccount(AccName,AccKey); | |
return AddOperation(TableName,DataModel,sa); | |
} | |
internal static bool AddOperation(string TableName, ITableEntity DataModel, CloudStorageAccount sa) | |
{ | |
CloudTableClient tc = sa.CreateCloudTableClient(); | |
CloudTable ct = tc.GetTableReference(TableName); | |
ct.CreateIfNotExistsAsync(); | |
TableOperation b = TableOperation.InsertOrReplace(DataModel); | |
try | |
{ | |
ct.ExecuteAsync(b); | |
return true; | |
} | |
catch (Exception ex) | |
{ | |
string temp = ex.Message; | |
// Call Logger | |
return false; | |
} | |
} | |
} | |
} |
Refactor The Get Operation Helper
Same as the Add Operation refactoring, we create an internal protected operation with 2 public method that is open to clients.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Threading.Tasks; | |
using Microsoft.WindowsAzure.Storage; | |
using Microsoft.WindowsAzure.Storage.RetryPolicies; | |
using Microsoft.WindowsAzure.Storage.Table; | |
namespace AzureTableseStorage | |
{ | |
public static class Get | |
{ | |
public static class List | |
{ | |
public async static Task< List<T>> All<T>(string TableName , string AccName, string AccKey) where T : TableEntity, new() | |
{ | |
try | |
{ | |
List<T> Data = new List<T>(); | |
CloudStorageAccount storageAccount = AzureSettings.SetupAccount(AccName,AccKey); | |
return GetOperation(TableName,storageAccount); | |
} | |
catch (Exception ex) | |
{ | |
string temp = ex.Message; | |
// Call Logger | |
return null; | |
} | |
} | |
public async static Task< List<T>> All<T>(string TableName , bool IsLive) where T : TableEntity, new() | |
{ | |
try | |
{ | |
List<T> Data = new List<T>(); | |
CloudStorageAccount storageAccount = AzureSettings.SetupAccount(IsLive); | |
return GetOperation(TableName,storageAccount); | |
} | |
catch (Exception ex) | |
{ | |
string temp = ex.Message; | |
// Call Logger | |
return null; | |
} | |
} | |
internal async static Task<List<T>> GetOperation(string TableName, CloudStorageAccount storageAccount) | |
{ | |
CloudTableClient tableClient = storageAccount.CreateCloudTableClient(); | |
tableClient.DefaultRequestOptions.RetryPolicy = new ExponentialRetry(TimeSpan.FromSeconds(1), 10); | |
CloudTable table = tableClient.GetTableReference(TableName); | |
//await table.CreateIfNotExistsAsync(); | |
TableContinuationToken tableContinuationToken = null; | |
do | |
{ | |
TableQuery<T> query = new TableQuery<T>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, TableName)); | |
try | |
{ | |
var queryResponse = await table.ExecuteQuerySegmentedAsync<T>(query, tableContinuationToken, null, null); | |
tableContinuationToken = queryResponse.ContinuationToken; | |
Data.AddRange(queryResponse.Results); | |
} | |
catch (Exception exquery) | |
{ | |
Console.WriteLine(exquery.InnerException); | |
return null; | |
} | |
} | |
while (tableContinuationToken != null); | |
return Data; | |
} | |
} |
Consuming in WebAPI
We then may reference the library in our Web Api solution by calling it like below.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using SplashBanners = CrudAzureTableseStorage; | |
public class SplashBannerController : ApiController | |
{ | |
[HttpPost] | |
[Route("Api/SplashBanner/AddAzure")] | |
public bool AddAzurestring ( | |
string SplashBannerID, | |
string Title, | |
string Description, | |
string ButtonTitle, | |
string ButtonURL, | |
string ImageURL) | |
{ | |
// Perform Validation | |
// Perform Audit Trail, | |
// Check Authorization/RBAC, | |
// Logging Or Other CrossCutting Concern in typical Middle Tier Layer | |
return SplashBanners.Add.New(SplashBannerID, Title, Description,ButtonTitle, ButtonURL, ImageURL , false); | |
} | |
} |
Conclusion
From the article we may conclude that we may place all the related CRUD operations in a data access layer and reference it in our WebApi for consumption.
Back - Azure > Azure Storage
Published on : 7-May-2018
Ref no : DDN-WPUB-000015
About Author

Comments
Post a Comment