Taylohtio/IDP/webapi/webapi.Infrastructure.Common/Repositories/Abstract/BaseRepository.cs

227 lines
9.0 KiB
C#

using Microsoft.Azure.CosmosDB.Table;
using Microsoft.Azure.Storage;
using Serilog;
using System;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
using webapi.Domain.Events;
using webapi.Domain.SeedWork;
namespace webapi.Infrastructure.Repositories
{
public class BaseAzureRepository<T>: IBaseRepository<T> where T : Entity
{
private static CloudStorageAccount CreateStorageAccountFromConnectionString(string storageConnectionString)
{
CloudStorageAccount storageAccount;
try
{
storageAccount = CloudStorageAccount.Parse(storageConnectionString);
}
catch (FormatException)
{
Console.WriteLine("Invalid storage account information provided. Please confirm the AccountName and AccountKey are valid in the app.config file - then restart the application.");
throw;
}
catch (ArgumentException)
{
Console.WriteLine("Invalid storage account information provided. Please confirm the AccountName and AccountKey are valid in the app.config file - then restart the sample.");
Console.ReadLine();
throw;
}
return storageAccount;
}
protected readonly CloudTable _table;
protected readonly ILogger _log;
private readonly EventsHandlerFactory _eventsFactory;
public BaseAzureRepository(ILogger log, string storageConnectionString, EventsHandlerFactory eventsFactory)
{
_log = log;
_eventsFactory = eventsFactory;
//string storageConnectionString = ConfigurationManager.ConnectionStrings["AzureProdConnectionString"].ConnectionString; //AppSettings.LoadAppSettings().StorageConnectionString;
// Retrieve storage account information from connection string.
CloudStorageAccount storageAccount = CreateStorageAccountFromConnectionString(storageConnectionString);
// Create a table client for interacting with the table service
CloudTableClient tableClient = storageAccount.CreateCloudTableClient(
new TableConnectionPolicy() {
UseDirectMode = false
}); // new TableClientConfiguration());
var tableName = typeof(T).Name;
System.Attribute[] attrs = Attribute.GetCustomAttributes(typeof(T));
if (attrs != null && attrs.Any())
{
var tableAttr = (attrs.FirstOrDefault() as TableAttribute);
if (tableAttr != null)
tableName = tableAttr.Name;
}
// Create a table client for interacting with the table service
var table = tableClient.GetTableReference(tableName);
if (table.CreateIfNotExists())
{
//Console.WriteLine("Created Table named: {0}", tableName);
}
else
{
//Console.WriteLine("Table {0} already exists", tableName);
}
this._table = table;
}
public async Task DeleteEntityAsync(T deleteEntity)
{
try
{
if (deleteEntity == null)
{
throw new ArgumentNullException("deleteEntity");
}
if (deleteEntity.DomainEvents != null)
{
foreach (var evt in deleteEntity.DomainEvents)
{
//Process event
_eventsFactory.ResolveAndRun(evt);
}
}
TableOperation deleteOperation = TableOperation.Delete(deleteEntity);
TableResult result = await _table.ExecuteAsync(deleteOperation);
// Get the request units consumed by the current operation. RequestCharge of a TableResult is only applied to Azure CosmoS DB
//if (result.RequestCharge.HasValue)
//{
// Console.WriteLine("Request Charge of Delete Operation: " + result.RequestCharge);
//}
}
catch (StorageException e)
{
//Console.WriteLine(e.Message);
//Console.ReadLine();
throw e;
}
}
public async Task<T> SaveChanges(T entity, bool skipEntitySaving = false)
{
try
{
if (entity.DomainEvents != null)
{
foreach (var evt in entity.DomainEvents)
{
//Process event
_eventsFactory.ResolveAndRun(evt);
}
}
if(skipEntitySaving)
{
return entity;
}
_log.Information($"Start SaveChanges");
TableOperation insertOrMergeOperation = TableOperation.InsertOrMerge(entity);
_log.Information($"Execute the operation.");
TableResult result = await _table.ExecuteAsync(insertOrMergeOperation);
_log.Information($"End SaveChanges");
// Get the request units consumed by the current operation. RequestCharge of a TableResult is only applied to Azure Cosmos DB
//if (result.RequestCharge.HasValue)
//{
// Console.WriteLine("Request Charge of InsertOrMerge Operation: " + result.RequestCharge);
//}
return result.Result as T;
}
catch (StorageException e)
{
_log.Error($"Error SaveChanges StorageException {e.Message} {e.StackTrace} {e.InnerException}", e.Message);
throw e;
}
catch (Exception e)
{
_log.Error($"Error SaveChanges Exception {e.Message} {e.StackTrace} {e.InnerException}", e.Message);
throw e;
}
}
public void BatchOperation(T entity)
{
Console.WriteLine("******************** Start Batch Operation ********************");
var batchOperation = new TableBatchOperation();
for (var i = 2; i < 52; i++)
{
// I will create and add users and send them as one batch to the table.
//var batchUser = new User("Karlsbad", "Admin_" + i)
//{
// EMail = "alugili@gmail.com",
// LastLogin = DateTimeOffset.UtcNow
//};
batchOperation.Add(TableOperation.InsertOrMerge(entity)); // batchUser));
}
// Executing the operations or adding the users.
_table.ExecuteBatch(batchOperation);
Console.WriteLine("******************** End Batch Operation ********************");
}
public void ConcurrencyDemoDefaultPessimistic(CloudTable cloudTable)
{
Console.WriteLine("**************************** Start Demonstrate pessimistic concurrency ****************************");
//// Add new user to table.
//var firstUser = new User("Karlsruhe", "Operator")
//{
// EMail = "alugili@gmail.com",
// LastLogin = DateTimeOffset.UtcNow
//};
//var insertOrReplaceOperation = TableOperation.InsertOrReplace(firstUser);
//cloudTable.Execute(insertOrReplaceOperation);
//Console.WriteLine("Entity added. Original ETag = {0}", firstUser.ETag);
//// Someone else has changed the first user!
//var updatedFirstUser = new User("Karlsruhe", "Operator")
//{
// EMail = "bassam.alugili@hotmail.de",
// LastLogin = DateTimeOffset.UtcNow
//};
//insertOrReplaceOperation = TableOperation.InsertOrReplace(updatedFirstUser);
//cloudTable.Execute(insertOrReplaceOperation);
//Console.WriteLine("Entity updated. Updated ETag = {0}", updatedFirstUser.ETag);
//// Try updating first user. Etag is cached within firstUser and passed by default
//firstUser.LastLogin = DateTimeOffset.UtcNow;
//insertOrReplaceOperation = TableOperation.Merge(firstUser);
//try
//{
// Console.WriteLine("Trying to update Original entity");
// cloudTable.Execute(insertOrReplaceOperation);
//}
//catch (StorageException ex)
//{
// if (ex.RequestInformation.HttpStatusCode == (int)HttpStatusCode.PreconditionFailed)
// {
// Console.WriteLine("Error: Entity Tag is changed!");
// }
// else
// {
// throw;
// }
//}
Console.WriteLine("**************************** End Demonstrate pessimistic concurrency ****************************");
}
}
}