Realizaremos una práctica en la que vamos a aprender crear y utilizar uno de los servicios que nos ofrece el Portal de Azure que es el Storage Accounts/ Cuentas de Almacenamiento y más concreto el servicio de Table Service/ Servicio de Tabla.

Para el desarrollo del ejercicio necesitaremos de nuestro entorno de Visual Studio y de una cuenta en Azure previamente creada. Si no desea crear una cuenta en el Portal de Azure, también puede utilizar el emulador de Almacenamiento de Azure para ejecutar y probar el código en un entorno local.

Que es el Servicio de Tabla?

El Servicio de Tabla de Windows Azure Storage sirve para almacenar grandes conjuntos de datos estructurados no relacionales y realizar consultas sobre ellos, y las tablas se escalarán a medida que aumente la demanda. Estas tablas funcionan de un modo diferente a las tablas relacionales de una base de datos.
Que es una tabla?

Una tabla es una colección de entidades. Cada tabla está formada por una serie de entidades que representan las filas y cada una de estas entidades contiene una serie de propiedades que son las columnas. Las tablas no exigen un esquema sobre entidades, lo que significa que una única tabla puede contener entidades que dispongan de diferentes conjuntos de propiedades.

Que es una entidad?

Una entidad es un conjunto de propiedades, similar a una fila de base de datos. Una entidad puede tener un tamaño de hasta 1 MB.

Que son las propiedades?

Una propiedad es un par nombre-valor. Cada entidad puede incluir hasta 252 propiedades para almacenar datos. Cada entidad dispone también de tres propiedades del sistema que especifican una clave de partición, una clave de fila y una marca de tiempo. Pueden realizarse consultas en las entidades con la misma partición de manera más rápida e insertarse o actualizarse en operaciones atómicas. Una clave de fila de la entidad es el identificador exclusivo en una partición.
Las tablas tienen dos campos obligatorios que son RowKey y PartitionKey.
PartitionKey es la primera propiedad de una entidad, el sistema la utiliza para distribuir la información entre nodos.

RowKey, es la segunda propiedad de la entidad, es el identificador único de la entidad dentro de la partición.

Vamos a empezar creando nuestra primera cuenta de Almacenamiento de Azure mediante el Portal de Azure. Buscaremos en la barra lateral de navegación la pestaña de Storage Accounts/Cuentas de Almacenamiento y la seleccionamos. Para el ejercicio nos basta con poner le nombre, elegir tipo de suscripción, asignar grupo de recursos y localización. El resto de campos los podemos dejar por defecto.

createstorage

Ya tenemos creada nuestra cuenta de Almacenamiento con su Servicio de Tabla todavía vacio.

storagecreadedempty

Una vez creada la cuenta nos vamos en la pestaña de Access keys/ Claves de Acceso en el menú lateral y lo abrimos. Dentro encontramos el nombre y dos claves de acceso que nos proporciona Azure. Los tendremos a mano para poder usar los más tarde en la configuración de la cadena de conexión.

accesskey

Para visualizar la aplicación en un entorno real y crear la tabla, vamos a crearnos una nueva aplicación MVC llamada ActoresTablaAzure.

newproject

Elegiremos la plantilla de MVC.

newproject

Una vez creado el proyecto nos vamos al Explorador de Solución y pulsamos con el botón derecho. Elegiremos la opción de Manage NuGet Packages for Solution. Debemos buscar e instalar los paquetes de Microsoft.Azure.KeyVault.CoreMicrosoft.WindowsAzure.ConfigurationManager

azurekeyvault
azureconnfigurationmanager

Ahora vamos a configurar nuestra cadena de conexión para conectarnos a nuestra cuenta de Almacenamiento de Azure.  Copiaremos el nombre y una de las claves de acceso del Portal de Azure y las incluimos en la cadena de conexión en el archivo de Web.config.

<appSettings>

<add key=”StorageConnectionString” value=”DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account key” />

</appSettings>

En caso que va a ultilizar el emulador deberia de escribir lo siguente en el archivo de Web.c:

<add key=”StorageConnectionString” value=”UseDevelopmentStorage=true;” />
Sobre la carpeta Models, nos vamos a agregar una nueva clase llamada Actor, que deberá heredar de TableEntity y deberá tener Rowkey y Partition Key.

Clase Actor

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

namespace ActoresTablaAzure.Models
{          
    public class Actor: TableEntity        
    {              
       public Actor(string IdActor, String pelicula)              
       {                     
         this.PartitionKey = pelicula;                     
         this.RowKey = IdActor;                    

        //INDICAMOS LA FECHA Y HORA DEL INGRESO DEL ACTOR                    
         this.Timestamp = new DateTimeOffset(DateTime.Now);                     
         this.IdActor = IdActor;               
       }          

       public Actor()           
       {             
         this.Timestamp = new DateTimeOffset(DateTime.Now);          
       }          

       public String Nombre { get; set; }           
       public String Apellidos { get; set; }           
       public string IdActor { get; set; }       
    } 
}

Ahora nos vamos a crear otra clase llamada  ModeloActoresStorage dentro en la carpeta de Models. Con esta clase vamos a  administrar la tabla que crearemos en el servidor.

Clase ModeloActoresStorage.

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

namespace ActoresTablaAzure.Models
{
    public class ModeloActoresStorage
    {
       //CAMPO PARA RECUPERAR LA TABLA CON
       public CloudTable Tabla { get; set; }

       //DECLARAMOS UN OBJETO STORAGE PARA PODER ACCEDER A LA CUENTA
       CloudStorageAccount storageAccount;

       public ModeloActoresStorage()
       {
          //CREAMOS EL OBJETO STORAGE A PARTIR DE LA CADENA DE CONEXION
          storageAccount = CloudStorageAccount.Parse(
          CloudConfigurationManager.GetSetting("StorageConnectionString"));
       }

       //METODO PARA CREAR LA TABLA DE AZURE SI NO EXISTE
       public CloudTable CrearTablaAzureStorage()
       {
          //CREAMOS UN OBJETO TABLA
          CloudTableClient tableActores = storageAccount.CreateCloudTableClient();

          //RECUPERAMOS LA TABLA DE REFERENCIA
          CloudTable tabla = tableActores.GetTableReference("mitablaactores");

          //SI NO EXISTE LA TABLA LA CREAMOS
          tabla.CreateIfNotExists();
          return tabla;
       }

      //METODO PARA INSERTAR Y GUARDAR UN ACTOR EN LA TABLA
      public void GuardarActorTabla(String idactor, String nombre, String apellidos, String pelicula)
      {
         this.Tabla = this.CrearTablaAzureStorage();
         Actor ac = new Actor(idactor, pelicula);
         ac.Nombre = nombre;
         ac.Apellidos = apellidos;

         // INSERTAR
         TableOperation insertOperation = TableOperation.Insert(ac);

         // EJECUTAR
         Tabla.Execute(insertOperation);
      }

    //MÉTODO PARA RECUPERAR TODOS LOS ACTORES
    public List<Actor> GetActoresPeliculas(String partitionkey)
    {
       CloudTable tabla = this.CrearTablaAzureStorage();
       TableQuery<Actor> consulta = new TableQuery<Actor>()
       .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionkey));
       List<Actor> lista = tabla.ExecuteQuery(consulta).ToList();

       if (lista.Count != 0)
       {
           return lista;
       }
       else
       {
           return null;
       }
    }

    //MÉTODO PARA BUSCAR UN ACTOR POR SU ROWKEY
    public Actor GetActorTabla(String partitionkey, String rowkey)
    {
       CloudTable tabla = this.CrearTablaAzureStorage();
       TableOperation consulta = TableOperation.Retrieve<Actor>(partitionkey, rowkey);
       TableResult respuesta = tabla.Execute(consulta);

       if (respuesta.Result != null)
       {
          Actor ac = (Actor)respuesta.Result;
          return ac;
       }
       else
       {
          return null;
       }
     }
   }
}

A continuación, nos creamos un Controlador vacío llamada ActoresController.

Vamos a crearnos una acción para crear objetos Actor en un ActionResult llamado InsertarActor.

ActoresController

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
//using
using ActoresTablaAzure.Models;

namespace ActoresTablaAzure.Controllers
{
   public class ActoresController : Controller
   {
      ModeloActoresStorage modelo;

      public ActoresController()
      {
         this.modelo = new ModeloActoresStorage();
      }

      // GET: Insertar
      public ActionResult InsertarActor()
      {
         return View();
      }

     // POST: Insertar
     [HttpPost]
     public ActionResult InsertarActor(String idactor, String nombre, String apellidos, String pelicula)
     {
        this.modelo.GuardarActorTabla(idactor, nombre, apellidos, pelicula);
        ViewBag.Mensaje = "Actor creado en tabla correctamente.";
        return View();
     }

     //Get BuscarActorPelicula public ActionResult BuscarActorPelicula()
     {
       return View();
     }

    //Post BuscarActorPelicula
    [HttpPost]
    public ActionResult BuscarActorPelicula(string pelicula)
    {
       List<Actor> lista = this.modelo.GetActoresPeliculas(pelicula);
       if (lista == null)
       {
          ViewBag.Mensaje = "No se han encontrado actores";
          return View();
       }
       else
       {
          return View(lista);
       }
    }

    //Get MostrarActor
    public ActionResult MostrarActor(String rowkey, String partitionkey)
    {
       Actor ac = this.modelo.GetActorTabla(partitionkey, rowkey);
       if (ac == null)
       {
          ViewBag.Mensaje = "No se ha encontrado ningún actor";
          return View();
       }
       else
       {
          return View(ac);
       }
    }
  }
}

La vista de InsertarActor seria:

@{
 ViewBag.Title = "InsertarActor";
 }

<h2>Crear un nuevo actor en Storage Table</h2>

<form method="post">
   <div>
     <label>Id actor: </label>
     <input type="text" name="idactor" class="form-control" placeholder="Id actor" />
   </div>
   <div>
     <label>Nombre: </label>
     <input type="text" name="nombre" class="form-control" placeholder="Nombre" />
   </div>
   <div>
     <label>Apellidos: </label>
     <input type="text" name="apellidos" class="form-control" placeholder="Apellidos" />
   </div>
   <div>
     <label>Pelicula: </label>
     <input type="text" name="pelicula" class="form-control" placeholder="Nombre de la pelicula" />
   </div>
   <div>
     <button type="submit" class="btn-success">Insertar actor</button>
   </div>
   </form>
   <hr />
   <h2 style="color:green">@ViewBag.Mensaje</h2>

Vista BuscarActorPelicula:

@{
 ViewBag.Title = "BuscarActorPelicula";
 }
@model List<ActoresTablaAzure.Models.Actor>

<h2>Buscar Actor Pelicula</h2>
<p>
   @Html.ActionLink("Insertar", "InsertarActor")
</p>

<form method="post">
   <label>Buscar actor por pelicula</label>
   <input type="text" name="pelicula" class="form-control" placeholder="Pelicula de los actores" />
   <button type="submit" class="btn-success">Buscar actores de pelicula</button>
</form>

<hr />

<h2 style="color:red">@ViewBag.Mensaje</h2>

@if (Model != null)
 {
    <table class="table">
      <tr>
         <th>PELICULA</th>
         <th>ID ACTOR</th>
         <th>TIEMPO</th>
         <th>NOMBRE</th>
         <th>APELLIDOS</th>
         <th>ID ACTOR</th>
     </tr>

@foreach (var item in Model)
 { 
   <tr>
       <td>@Html.DisplayFor(modelItem => item.PartitionKey)</td>
       <td>@Html.DisplayFor(modelItem => item.RowKey)</td>
       <td>@Html.DisplayFor(modelItem => item.Timestamp)</td>
       <td>@Html.DisplayFor(modelItem => item.Nombre)</td>
       <td>@Html.DisplayFor(modelItem => item.Apellidos)</td>
       <td>@Html.DisplayFor(modelItem => item.IdActor)</td>
       <td>@Html.ActionLink("Datos del actor", "MostrarActor"
       , new
       {
           rowkey = item.RowKey
           , partitionkey = item.PartitionKey
       })</td>
  </tr>
}
</table>
}

Vista MostrarActor

@{ 
ViewBag.Title = "MostrarActor"; 
} 
<h2>Acciones sobre Storage Table</h2>
   <ul> 
        <li> @Html.ActionLink("Insertar nuevo actor", "InsertarActor", "Actores") </li>
        <li> @Html.ActionLink("Buscar actores pelicula", "BuscarActorPelicula", "Actores") </li>
   </ul>

Aquí ya tenemos nuestra tabla que nos muestra los objetos que hemos creado.

mvcres

Descripción: Con este post aprenderemos a crear y administrar el servicio de Almacenimiento de Tabla que nos ofrece el Portal de Azure.

Autor: Lyudmila Petrova

Curso: Microsoft MCSD Web Applications & SharePoints Apps

Centro: Tajamar

Año académico: 2016/2017