¿Azure vs Azure? Hablando de Bases de Datos

La evolución de Microsoft Azure ha sido constante y dinámica, tiene todo lo que necesitas y si no lo tiene, muy seguramente en el siguiente «release» lo verás en alguna parte.

Este artículo (el primero de muchos en su estilo), abordará que hay actualmente en Microsoft Azure cuando necesitamos trabajar con bases de datos.

Lo que sigue, son una serie de preguntas que irán discriminando entre una y otra opción hasta reflexionar que se adapta mejor a nuestras necesidades.

¿Bases de Datos Relacionales ó NoSQL?

Solo como referencia diremos que las bases de datos relacionales son aquellas que tienen la característica principal de almacenar información mediante estructuras construidas por filas y columnas «tablas», la información se distingue y relaciona por medio de identificadores numéricos irrepetibles para cada registro.

Las bases de datos relacionales dominaron el mercado por décadas completas, y si bien su uso todavía está vigente, ya vivimos en un mundo lleno de aplicaciones y plataformas donde los datos proliferan considerablemente, así que un esquema convencional como las bases de datos relacionales no encaja del todo como solución en cuestiones de rendimiento y agilidad para lectura-escritura en tiempo real.

Otra cara del cubo son las bases de datos NoSQL (No Relacionales), aquellas donde los datos no tienen un tipo en específico ni esquema obligatorio, los formatos de almacenamiento se dan como:

  • Documentos (formato JSON, menos verboso que XML).
  • Clave Valor.
  • Grafos.
  • Columnar.

Identificado lo anterior ¿Qué tiene Microsoft Azure para nosotros?

 

Azure SQL Database

Es el servicio de bases de datos relacionales de Microsoft Azure, SI es administrado. Nos limitamos a conectarnos para realizar transacciones de escritura y lectura.

Microsoft SQL Server

El motor de bases de datos por excelencia de Microsoft, NO es administrado. Se tiene instalada una versión de Microsoft SQL Server en una máquina virtual y a partir de ahí se configura todo.

Azure for MySQL

Es el servicio de bases de datos relacionales de Microsoft Azure para MySQL, SI es administrado. Nos limitamos a conectarnos para realizar transacciones de escritura y lectura.

Azure for MariaDB

Es el servicio de bases de datos relacionales de Microsoft Azure para MariaDB, SI es administrado. Nos limitamos a conectarnos para realizar transacciones de escritura y lectura.

Azure for PostgreDB

Es el servicio de bases de datos relacionales de Microsoft Azure para PostgreDB, SI es administrado. Nos limitamos a conectarnos para realizar transacciones de escritura y lectura.

Demostración de trabajo con MySQL y PostgreDB

Demostración de trabajo con Table Storage

Table Storage en esencia se maneja desde código, a continuación expondré el código C# para realizar múltiples operaciones con Table Storage en un proyecto ASP.Net MVC (código completo clic aquí).

Para deslizar hacia abajo presiona el ícono «<>».

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Table;
using Microsoft.Azure;

namespace AzureTableStorage.Models
{
    public class CustomerEntity : TableEntity
    {
        public CustomerEntity(string lastName, string firstName)
        {
            this.PartitionKey = lastName;
            this.RowKey = firstName;
        }

        public CustomerEntity() { }

        public string Email { get; set; }

        public string PhoneNumber { get; set; }

    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Table;
using Microsoft.Azure;
using Microsoft.WindowsAzure.ServiceRuntime;
using System.Windows.Forms;

namespace AzureTableStorage.Models
{
    public class MyTableStorage
    {
        private string Account { get; set; }
        private string Key { get; set; }

        public MyTableStorage()
        {
            this.Account = "otheraccount";
            this.Key = "";
        }

        public void Create_a_table()
        {
            //Retrieve the storage account from the connection string.
            StorageCredentials Credentials = new StorageCredentials(this.Account, this.Key);            
            CloudStorageAccount storageAccount = new CloudStorageAccount(Credentials, false);

            // Create the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

            // Retrieve a reference to the table.
            CloudTable table = tableClient.GetTableReference("Demo");

            // Create the table if it doesn't exist.
            table.CreateIfNotExists();
            MessageBox.Show("Table created", "Entity", MessageBoxButtons.OK);
        }

        public void Add_an_entity_to_a_table()
        {
            //Retrieve the storage account from the connection string.
            StorageCredentials Credentials = new StorageCredentials(this.Account, this.Key);
            CloudStorageAccount storageAccount = new CloudStorageAccount(Credentials, false);


            // Create the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

            // Create the CloudTable object that represents the "Demo" table.
            CloudTable table = tableClient.GetTableReference("Demo");

            // Create a new customer entity.
            CustomerEntity customer1 = new CustomerEntity("Harp", "Walter");
            customer1.Email = "Walter@contoso.com";
            customer1.PhoneNumber = "425-555-0101";

            // Create the TableOperation object that inserts the customer entity.
            TableOperation insertOperation = TableOperation.Insert(customer1);

            // Execute the insert operation.
            table.Execute(insertOperation);
            MessageBox.Show("Entity added", "Entity", MessageBoxButtons.OK);
        }

        public void Add_a_batch_of_entities()
        {
            //Retrieve the storage account from the connection string.
            StorageCredentials Credentials = new StorageCredentials(this.Account, this.Key);
            CloudStorageAccount storageAccount = new CloudStorageAccount(Credentials, false);

            // Create the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

            // Create the CloudTable object that represents the "Demo" table.
            CloudTable table = tableClient.GetTableReference("Demo");

            // Create the batch operation.
            TableBatchOperation batchOperation = new TableBatchOperation();

            // Create a customer entity and add it to the table.
            CustomerEntity customer1 = new CustomerEntity("Smith", "Jeff");
            customer1.Email = "Jeff@contoso.com";
            customer1.PhoneNumber = "425-555-0104";

            // Create another customer entity and add it to the table.
            CustomerEntity customer2 = new CustomerEntity("Smith", "Ben");
            customer2.Email = "Ben@contoso.com";
            customer2.PhoneNumber = "425-555-0102";

            // Add both customer entities to the batch insert operation.
            batchOperation.Insert(customer1);
            batchOperation.Insert(customer2);

            // Execute the batch operation.
            table.ExecuteBatch(batchOperation);
            MessageBox.Show("Several entities added", "Entity", MessageBoxButtons.OK);
        }

        public void Retrieve_all_entities_in_a_partition()
        {
            //Retrieve the storage account from the connection string.
            StorageCredentials Credentials = new StorageCredentials(this.Account, this.Key);
            CloudStorageAccount storageAccount = new CloudStorageAccount(Credentials, false);

            // Create the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

            // Create the CloudTable object that represents the "Demo" table.
            CloudTable table = tableClient.GetTableReference("Demo");

            // Construct the query operation for all customer entities where PartitionKey="Smith".
            TableQuery<CustomerEntity> query = new TableQuery<CustomerEntity>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "Smith"));

            MessageBox.Show("Receiving entities by partition", "Entity", MessageBoxButtons.OK);

            // Print the fields for each customer.
            foreach (CustomerEntity entity in table.ExecuteQuery(query))
            {
                MessageBox.Show(entity.PartitionKey + " " +
                                entity.RowKey + " " +
                                entity.Email + " " +
                                entity.PhoneNumber + " ",
                                "Entity", MessageBoxButtons.OK
                                );
                Console.WriteLine("{0}, {1}\t{2}\t{3}", entity.PartitionKey, entity.RowKey,
                    entity.Email, entity.PhoneNumber);
            }
        }

        public void Retrieve_a_range_of_entities_in_a_partition()
        {
            //Retrieve the storage account from the connection string.
            StorageCredentials Credentials = new StorageCredentials(this.Account, this.Key);
            CloudStorageAccount storageAccount = new CloudStorageAccount(Credentials, false);

            // Create the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

            // Create the CloudTable object that represents the "Demo" table.
            CloudTable table = tableClient.GetTableReference("Demo");

            // Create the table query.
            TableQuery<CustomerEntity> rangeQuery = new TableQuery<CustomerEntity>().Where(
                TableQuery.CombineFilters(
                    TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "Smith"),
                    TableOperators.And,
                    TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThan, "E")));

            MessageBox.Show("Receiving entities by range", "Entity", MessageBoxButtons.OK);

            // Loop through the results, displaying information about the entity.
            foreach (CustomerEntity entity in table.ExecuteQuery(rangeQuery))
            {
                MessageBox.Show(entity.PartitionKey + " " +
                               entity.RowKey + " " +
                               entity.Email + " " +
                               entity.PhoneNumber + " ",
                               "Entity", MessageBoxButtons.OK
                               );

                Console.WriteLine("{0}, {1}\t{2}\t{3}", entity.PartitionKey, entity.RowKey,
                    entity.Email, entity.PhoneNumber);
            }
        }

        public void Retrieve_a_single_entity()
        {
            //Retrieve the storage account from the connection string.
            StorageCredentials Credentials = new StorageCredentials(this.Account, this.Key);
            CloudStorageAccount storageAccount = new CloudStorageAccount(Credentials, false);

            // Create the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

            // Create the CloudTable object that represents the "Demo" table.
            CloudTable table = tableClient.GetTableReference("Demo");

            // Create a retrieve operation that takes a customer entity.
            TableOperation retrieveOperation = TableOperation.Retrieve<CustomerEntity>("Smith", "Ben");

            // Execute the retrieve operation.
            TableResult retrievedResult = table.Execute(retrieveOperation);

            MessageBox.Show("Receiving by single entity", "Entity", MessageBoxButtons.OK);

            // Print the phone number of the result.
            if (retrievedResult.Result != null)
            {
                MessageBox.Show(((CustomerEntity)retrievedResult.Result).PhoneNumber, "Entity", MessageBoxButtons.OK);
                Console.WriteLine(((CustomerEntity)retrievedResult.Result).PhoneNumber);
            }
                
            else
                Console.WriteLine("The phone number could not be retrieved.");
        }
        public void Replace_an_entity()
        {
            //Retrieve the storage account from the connection string.
            StorageCredentials Credentials = new StorageCredentials(this.Account, this.Key);
            CloudStorageAccount storageAccount = new CloudStorageAccount(Credentials, false);

            // Create the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

            // Create the CloudTable object that represents the "Demo" table.
            CloudTable table = tableClient.GetTableReference("Demo");

            // Create a retrieve operation that takes a customer entity.
            TableOperation retrieveOperation = TableOperation.Retrieve<CustomerEntity>("Smith", "Ben");

            // Execute the operation.
            TableResult retrievedResult = table.Execute(retrieveOperation);

            // Assign the result to a CustomerEntity object.
            CustomerEntity updateEntity = (CustomerEntity)retrievedResult.Result;

            if (updateEntity != null)
            {
                // Change the phone number.
                updateEntity.PhoneNumber = "425-555-0105";

                // Create the Replace TableOperation.
                TableOperation updateOperation = TableOperation.Replace(updateEntity);

                // Execute the operation.
                table.Execute(updateOperation);

                Console.WriteLine("Entity updated.");
                MessageBox.Show("Entity updated", "Entity", MessageBoxButtons.OK);
            }

            else
                Console.WriteLine("Entity could not be retrieved.");
        }

        public void Insert_or_replace_an_entity()
        {
            //Retrieve the storage account from the connection string.
            StorageCredentials Credentials = new StorageCredentials(this.Account, this.Key);
            CloudStorageAccount storageAccount = new CloudStorageAccount(Credentials, false);

            // Create the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

            // Create the CloudTable object that represents the "Demo" table.
            CloudTable table = tableClient.GetTableReference("Demo");

            // Create a retrieve operation that takes a customer entity.
            TableOperation retrieveOperation = TableOperation.Retrieve<CustomerEntity>("Smith", "Ben");

            // Execute the operation.
            TableResult retrievedResult = table.Execute(retrieveOperation);

            // Assign the result to a CustomerEntity object.
            CustomerEntity updateEntity = (CustomerEntity)retrievedResult.Result;

            if (updateEntity != null)
            {
                // Change the phone number.
                updateEntity.PhoneNumber = "425-555-1234";

                // Create the InsertOrReplace TableOperation.
                TableOperation insertOrReplaceOperation = TableOperation.InsertOrReplace(updateEntity);

                // Execute the operation.
                table.Execute(insertOrReplaceOperation);

                MessageBox.Show(updateEntity.PhoneNumber, "Entity", MessageBoxButtons.OK);

                Console.WriteLine("Entity was updated.");
                MessageBox.Show("Entity updated", "Entity", MessageBoxButtons.OK);
            }

            else
                Console.WriteLine("Entity could not be retrieved.");
        }

        public void Query_a_subset_of_entity_properties()
        {
            //Retrieve the storage account from the connection string.
            StorageCredentials Credentials = new StorageCredentials(this.Account, this.Key);
            CloudStorageAccount storageAccount = new CloudStorageAccount(Credentials, false);

            // Create the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

            // Create the CloudTable that represents the "Demo" table.
            CloudTable table = tableClient.GetTableReference("Demo");

            // Define the query, and select only the Email property.
            TableQuery<DynamicTableEntity> projectionQuery = new TableQuery<DynamicTableEntity>().Select(new string[] { "Email" });

            // Define an entity resolver to work with the entity after retrieval.
            EntityResolver<string> resolver = (pk, rk, ts, props, etag) => props.ContainsKey("Email") ? props["Email"].StringValue : null;

            MessageBox.Show("Receiving entitues by subset", "Entity", MessageBoxButtons.OK);

            foreach (string projectedEmail in table.ExecuteQuery(projectionQuery, resolver, null, null))
            {
                MessageBox.Show(projectedEmail, "Entity", MessageBoxButtons.OK);
                Console.WriteLine(projectedEmail);
            }
        }

        public void Delete_an_entity()
        {
            //Retrieve the storage account from the connection string.
            StorageCredentials Credentials = new StorageCredentials(this.Account, this.Key);
            CloudStorageAccount storageAccount = new CloudStorageAccount(Credentials, false);

            // Create the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

            // Create the CloudTable that represents the "Demo" table.
            CloudTable table = tableClient.GetTableReference("Demo");

            // Create a retrieve operation that expects a customer entity.
            TableOperation retrieveOperation = TableOperation.Retrieve<CustomerEntity>("Smith", "Ben");

            // Execute the operation.
            TableResult retrievedResult = table.Execute(retrieveOperation);

            // Assign the result to a CustomerEntity.
            CustomerEntity deleteEntity = (CustomerEntity)retrievedResult.Result;

            // Create the Delete TableOperation.
            if (deleteEntity != null)
            {
                TableOperation deleteOperation = TableOperation.Delete(deleteEntity);

                // Execute the operation.
                table.Execute(deleteOperation);

                Console.WriteLine("Entity deleted.");
                MessageBox.Show("Entity deleted", "Entity", MessageBoxButtons.OK);
            }

            else
                Console.WriteLine("Could not retrieve the entity.");
        }

        public void Delete_a_table()
        {
            //Retrieve the storage account from the connection string.
            StorageCredentials Credentials = new StorageCredentials(this.Account, this.Key);
            CloudStorageAccount storageAccount = new CloudStorageAccount(Credentials, false);

            // Create the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

            // Create the CloudTable that represents the "Demo" table.
            CloudTable table = tableClient.GetTableReference("Demo");

            // Delete the table it if exists.
            table.DeleteIfExists();
            MessageBox.Show("Table deleted", "Entity", MessageBoxButtons.OK);
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace AzureTableStorage.Controllers
{
    public class DefaultController : Controller
    {
        // GET: Default
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult WorkingWithTableStorage()
        {
            Models.MyTableStorage ObjectMyTableStorage = new Models.MyTableStorage();

            ObjectMyTableStorage.Create_a_table();
            ObjectMyTableStorage.Add_an_entity_to_a_table();
            ObjectMyTableStorage.Add_a_batch_of_entities();
            ObjectMyTableStorage.Retrieve_all_entities_in_a_partition();
            ObjectMyTableStorage.Retrieve_a_range_of_entities_in_a_partition();
            ObjectMyTableStorage.Retrieve_a_single_entity();
            ObjectMyTableStorage.Replace_an_entity();
            ObjectMyTableStorage.Insert_or_replace_an_entity();
            ObjectMyTableStorage.Query_a_subset_of_entity_properties();
            ObjectMyTableStorage.Delete_an_entity();
            ObjectMyTableStorage.Delete_a_table();

            return View("DefaultView");
        }
    }
}

Demostración de trabajo con SQL Database

Demostración de trabajo con MariaDB

¿Bases de Datos Administradas ó No Administradas?

Esta palabra la usamos en la pregunta anterior y está fuertemente asociada al paradigma de computo en la nube, vamos ahora marcando la distinción:

  • Servicio SI administrado: Es aquel qué no necesita intervención nuestra para su mantenimiento, es decir: actualizaciones de software/hardware y aspectos de seguridad. Nos limitamos a consumirlo conectándonos a él por medio de clientes o APIS mediante código, esquema PaaS.
  • Servicio NO administrado: Es aquel qué si necesita intervención nuestra para su mantenimiento, típicamente se abre un espacio de máquina virtual en la infraestructura de nuestro proveedor de nube Microsoft Azure y ahí mismo se instala, configura y se le da mantenimiento a nuestros servidores como si de un servidor físico se tratara puesto que se trata de un esquema IaaS.

Identificado lo anterior ¿Qué tiene Microsoft Azure para nosotros?

Hay que poner más atención en esta división, donde las bases de datos «No son administradas», la mención de Microsoft SQL Server va por que existen máquinas virtuales especialmente pre-configuradas con la más reciente versión del servidor, pero obviamente se podría tomar otra máquina virtual con nada de base y a partir de ahí descargar, instalar y configurar el servidor de nuestra preferencia tanto de los ya mencionados como algún otro, ese servidor virtual tendrá que abrir sus puertos y exponerse públicamente para conectarnos correctamente.

Demostración de trabajo con Microsoft SQL Server

¿Bases de Datos Distribuidas ó No Distribuidas?

Las bases de datos distribuidas son aquellas que se constituyen de múltiples bases de datos lógicamente relacionadas, pero física y hasta geográficamente separadas.

¿Recuerdas cómo surgió Facebook? Esa red social que empezó en un ambiente universitario y que prácticamente ahora su alcance es mundial. Vamos arrojando unas preguntas reflexivas que nos ayudarán a determinar si algo como Facebook requiere una base de datos distribuida:

  • ¿Cuántas conexiones de usuario existirán por segundo?
  • ¿Cuántas operaciones de lectura/escritura existirán por segundo?
  • ¿Desde qué zonas geográficas existirán solicitudes HTTP?
  • ¿Qué tan crítica es la información como para tenerla disponible siempre?

Identificado lo anterior ¿Qué tiene Microsoft Azure para nosotros?

Voy a destacar que Azure Cosmos DB se basa en un multimodelo de datos NoSQL, por lo que está en nosotros decidir si lo que guardaremos en ella será: documento, clave-valor, columnar o grafo.

¿Bases de Datos de Baja Latencia ó Basadas en Disco?

Redis es una base de datos muy «especial» y hago énfasis en ella puesto que la manera en la que mantiene la información es muy singular. Desde que nos enseñaron principios de computación sabemos que la memoria RAM es más rápida de lo que podría ser la memoria de disco duro. Dicho lo anterior podemos inferir que si nuestra base de datos está en memoria RAM, las operaciones de lectura-escritura serán más rápidas que si se realizaran a disco duro ¿cierto? bien pues eso es Redis.

Identificado lo anterior ¿Qué tiene Microsoft Azure para nosotros?

Demostración de trabajo con Azure Redis Cache

Redis Cache en esencia se maneja desde código, a continuación expondré el código C# para realizar múltiples operaciones con Redis Cache en un proyecto consola (código completo clic aquí).

Para deslizar hacia abajo presiona el ícono «<>».

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AzureRedisCache
{
    class Program
    {
        /*            
         * Comments:
         * 
         * For run this code without errors, you should to create an Azure Redis Cache Service in Microsoft Azure, and get your
         * own ConnectionString and passwords for the server .
         * Once you have your Azure Redis Cache service, now you need to set the property "SSL Port " no enabled if you don't do
         * this action, you can't run the code correctly.
         * Don't forget to add the reference StackExchange.Redis from Nuget Package also.
         * More references: 
         * 
         * API:
         * https://github.com/StackExchange/StackExchange.Redis/blob/master/StackExchange.Redis/StackExchange/Redis/IDatabase.cs
         * 
         * One tool that you can use for monitoring your redis data base is: Redis Desktop Manager from:
         * http://redisdesktop.com/
         */

        static void Main(string[] args)
        {
            try
            {
                string Value = "", Key = "";
                int Operation = 0;              

                RedisCache ServerAzureRedisCache = new RedisCache();

                do
                {
                    Console.Clear();

                    Console.WriteLine("* * * [ Azure Redis Cache Operations ] * * *");
                    Console.WriteLine();

                    Console.WriteLine(" 1) Save data.");
                    Console.WriteLine(" 2) Search data.");
                    Console.WriteLine(" 3) Update data.");
                    Console.WriteLine(" 4) Delete data.");
                    Console.WriteLine(" 5) List all data");
                    Console.WriteLine(" 0) Exit.");

                    Console.WriteLine();

                    Console.Write("Choose operation: ");
                    Operation = int.Parse(Console.ReadLine().Trim());
                    Console.WriteLine();

                    switch (Operation)
                    {
                        case 1:

                            /*
                             Code for save data in the Azure Redis Cache DataBase
                            */

                            Console.Write("Write one key to the data: ");
                            Key = Console.ReadLine().Trim();

                            Console.Write("Write one value to save: ");
                            Value = Console.ReadLine().Trim();

                            if(ServerAzureRedisCache.SaveData(Key, Value)==true)
                            {
                                Console.WriteLine("");
                                Console.WriteLine("Data saved successfully! [ Now press Enter ]");
                                Console.ReadLine();
                            }
                            else
                            {
                                Console.WriteLine("");
                                Console.WriteLine("Unsaved data [ Now press Enter ]");
                                Console.ReadLine();
                            }

                            break;

                        case 2:

                            /*
                              Code for search data in the Azure Redis Cache DataBase
                            */

                            Console.Write("Write the Key to search: ");
                            Key = Console.ReadLine().Trim();

                            string  ValueFound = ServerAzureRedisCache.SearchData(Key);

                            if (ValueFound!=null)
                                Console.WriteLine("The data is: " + ValueFound + " [ Now press Enter ]");
                    
                            else
                                Console.WriteLine("Data not found" + " [ Now press Enter ]");

                            Console.ReadLine();
                            
                            break;

                        case 3:

                            /*
                             Code for update data in the Azure Redis Cache DataBase
                             */

                            Console.Write("Write the Key to search: ");
                            Key = Console.ReadLine().Trim();

                            Console.Write("Write the new value: ");
                            Value = Console.ReadLine().Trim();

                            if (ServerAzureRedisCache.UpdateData(Key, Value) == true)
                            {
                                Console.WriteLine("");
                                Console.WriteLine("Data updated successfully! [ Now press Enter ]");
                                Console.ReadLine();
                            }
                            else
                            {
                                Console.WriteLine("");
                                Console.WriteLine("Data was not updated [ Now press Enter ]");
                                Console.ReadLine();
                            }

                            break;

                        case 4:

                            /*
                             Code for delete data in the Azure Redis Cache DataBase
                           */

                            Console.Write("Write the Key to delete: ");
                            Key = Console.ReadLine().Trim();

                            bool ResultDelete = ServerAzureRedisCache.DeleteData(Key);

                            if (ResultDelete == true)
                                Console.WriteLine("The data was deleted successfully!" + " [ Now press Enter ]");

                            else
                                Console.WriteLine("Data not found" + " [ Now press Enter ]");

                            Console.ReadLine();

                            break;

                        case 5:

                            /*
                             Code for list all data in the Azure Redis Cache DataBase
                           */

                            List<RedisObject> RedisObjects = ServerAzureRedisCache.ListKeys();

                            if (RedisObjects.Count()>0)
                            {
                                foreach (RedisObject RedisHash in RedisObjects)
                                {
                                    Console.Write(RedisHash.Key + " : ");
                                    Console.Write(RedisHash.Value);
                                    Console.WriteLine();
                                }

                                Console.WriteLine("");
                                Console.WriteLine("All hashes shown" + " [ Now press Enter ]");
                                Console.ReadLine();
                            }
                            else
                            {
                                Console.WriteLine("");
                                Console.WriteLine("No information at this time" + " [ Now press Enter ]");
                                Console.ReadLine();
                            }
                           

                            break;

                                           }
            
                } while (Operation!=0);
            }
            catch (Exception ex)
            {
                Console.Clear();
                Console.WriteLine("An error occurred. Detail: " + ex.Message + " [ Now press Enter ]");

                Console.Read();
            }
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StackExchange.Redis;

namespace AzureRedisCache
{
    public class RedisCache
    {
        public string HostName { get; set; }
        public string ConnectionString { get; set; }
        public int PortNoSSL { get; set; }

        /// <summary>
        /// The constructor of RedisCache Class has the connection string necessary to set connections with the Azure Cache Redis from Microsoft Azure.
        /// </summary>
        public RedisCache()
        {
            this.ConnectionString = 
            //"myserverazurerediscache.redis.cache.windows.net,abortConnect=false,password=wU7KEJJy4v3iEH6e0M/Pe74MJSUIbTXyk9SXRMt18vM=";
            "myrediserver.redis.cache.windows.net:6380,password=PKk1DRtF3PeESjv0+30wfP5M4NVy837s6OWBuyIOT1Q=,ssl=True,abortConnect=False";

            this.HostName =
            "myrediserver.redis.cache.windows.net";
            
            this.PortNoSSL = 6379;
        }
        /// <summary>
        /// This method search data by one  key in the Azure Redis Cache DataBase
        /// </summary>
        /// <param name="Value">Data to search</param>
        /// <returns>False if the data not exist, True if the data exist</returns>
        public string SearchData(string Key)
        {
            try
            {               
                ConnectionMultiplexer Connection = ConnectionMultiplexer.Connect(this.ConnectionString);

                var DataBase = Connection.GetDatabase();
                var Data = DataBase.StringGet(Key);

                return Data.ToString();
            }
            catch (Exception)
            {
                throw;
            }
        }
        /// <summary>
        /// Thie method save data in the Azure Redis Cache DataBase by one Key.
        /// </summary>
        /// <param name="Key">Name of key</param>
        /// <param name="Value">Value for the key</param>
        /// 
        public bool SaveData(string Key, string Value)
        {
            try
            {
                ConnectionMultiplexer Connection = ConnectionMultiplexer.Connect(this.ConnectionString);
                var DataBase = Connection.GetDatabase();

                return DataBase.StringSet(Key, Value);
            }
            catch (Exception)
            {
                
                throw;
            }
        }
        /// <summary>
        /// This method update an existing string by key
        /// </summary>
        /// <param name="Key">One existing key</param>
        /// <param name="NewValue">New value to update</param>
        /// <returns>True if exist the key, false if not exist the key</returns>
        public bool UpdateData(string Key, string NewValue)
        {
            try
            {
                ConnectionMultiplexer Connection = ConnectionMultiplexer.Connect(this.ConnectionString);

                var DataBase = Connection.GetDatabase();
                var Data = DataBase.StringGet(Key);

                if (Data.HasValue == true)
                    return DataBase.StringSet(Key, NewValue);

                else
                    return false;
            }
            catch (Exception)
            {

                throw;
            }
        }
        /// <summary>
        /// This method delete data in the Azure Redis Cache DataBase by one Key
        /// </summary>
        /// <param name="Key">One existing key</param>
        /// <returns>True if exist key, false if not exist the key</returns>
        public bool DeleteData(string Key)
        {
            try
            {
                ConnectionMultiplexer Connection = ConnectionMultiplexer.Connect(this.ConnectionString);
                var DataBase = Connection.GetDatabase();

                return DataBase.KeyDelete(Key);
            }
            catch (Exception)
            {
                
                throw;
            }
        }
        /// <summary>
        /// This method return all the strings existing in the Azure Redis Cache
        /// </summary>
        /// <returns>A list of objects type RedisObject</returns>
        public List<RedisObject> ListKeys()
        {
            try
            {
                List<RedisObject> KeyList = new List<RedisObject>();

                ConnectionMultiplexer Connection = ConnectionMultiplexer.Connect(this.ConnectionString);

                var Server = Connection.GetServer(this.HostName + ":" + this.PortNoSSL);

                var DataBase = Connection.GetDatabase();

                foreach (var Key in Server.Keys())
                {
                    KeyList.Add(new RedisObject()
                    {
                        Key = Key,
                        Value = DataBase.StringGet(Key),
                    });
                }

                return KeyList;
            }
            catch (Exception)
            {
                
                throw;
            }
        }     
    }
}

¿Múltiples orígenes de datos ó aislados?

El escenario más conveniente para tratar información, hablando en términos de dificultad y rapidez sería que todo venga de una sola base de datos, un único origen, sin embargo, en la vida real la naturaleza de los proyectos nos presenta situaciones diferentes.

Microsoft Azure nos provee de SQL Data Warehouse, un servicio que actúa como repositorio para unificar todos los datos que recogen los diversos sistemas de información. Hace énfasis en la captura de datos de diversas fuentes para fines analíticos.

Identificado lo anterior ¿Qué tiene Microsoft Azure para nosotros?

Como podemos ver, la oferta es amplia y se ajusta a muchos escenarios. Dependerá de la arquitectura de nuestras aplicaciones cual será la mas conveniente. Es importante destacar que por estar hablando de computo en la nube, las bases de datos se pueden escalar tanto vertical como horizontalmente, generando nuevas instancias de máquinas virtuales o incrementando en recursos físicos para un mejor rendimiento.

¿Y acaso existe algo para Big Data?

Big Data… es un tema que da para mucho más, responderemos a esta pregunta diciendo «SI» y se llama HDInsight. Un servicio dedicado a procesar información estructurada y no estructurada de manera masiva, pero de eso hablaremos con mayor profundidad en otra ocasión 🙂


Sígueme en Twitter @vmorenoz

¿Te gustó este artículo? Únete a Facebook en MicrosoftLand

También te podría gustar...