public async Task <IOperationExecutionInfo <TData> > GetAsync <TData>(string operationName, string id)
            where TData : class
        {
            var obj = await _tableStorage.GetDataAsync(
                OperationExecutionInfoEntity.GeneratePartitionKey(operationName),
                OperationExecutionInfoEntity.GenerateRowKey(id)) ?? throw new InvalidOperationException(
                                $"Operation execution info for {operationName} #{id} not yet exists");

            return(Convert <TData>(obj));
        }
 private static IOperationExecutionInfo <TData> Convert <TData>(OperationExecutionInfoEntity entity)
     where TData : class
 {
     return(new OperationExecutionInfo <TData>(
                operationName: entity.OperationName,
                id: entity.Id,
                lastModified: entity.LastModified,
                data: entity.Data is string dataStr
             ? JsonConvert.DeserializeObject <TData>(dataStr)
             : ((JToken)entity.Data).ToObject <TData>()));
 }
        public async Task <IOperationExecutionInfo <TData> > GetOrAddAsync <TData>(
            string operationName, string operationId, Func <IOperationExecutionInfo <TData> > factory) where TData : class
        {
            var entity = await _tableStorage.GetOrInsertAsync(
                partitionKey : OperationExecutionInfoEntity.GeneratePartitionKey(operationName),
                rowKey : OperationExecutionInfoEntity.GeneratePartitionKey(operationId),
                createNew : () =>
            {
                var result          = Convert(factory());
                result.LastModified = _systemClock.UtcNow.UtcDateTime;
                return(result);
            });

            return(Convert <TData>(entity));
        }