No Windows Azure existe uma tecnologia para armazenamento de dados estruturados chamada Table Services. Ainda estamos em CTP, então pode ser que tudo mude, mas já há uma gama razoável de tipos, e nos meus testes tudo funcionou bem. E tudo é feito baseado em Astoria (ADO.Net Data Services), o que facilita muito. O único problema que tive é que algumas funcionalidades que existem no Azure não estão disponíveis no development fabric/development storage, que é onde desenvolvemos localmente.

Ao utilizar o Table Services o Azure funciona apenas como um hospedeiro de dados na nuvem. A aplicação pode estar rodando em qualquer lugar que tenha acesso a chamadas HTTP (lembre que tudo vai via REST). Pode rodar inclusive no próprio Azure Hosting.

Estou trabalhando e estendendo umas demos disponibilizadas no PDC (você pode ver alguns vídeos aqui e aqui), e por isso os meus exemplos deste post vão seguir o código realizado no PDC. Infelizmente eles não liberaram o código, então vou eu mesmo colocar o código que fiz, e que está funcionando, aqui para vocês baixarem.

Antes de mais nada uma observação: Essa não é uma aplicação baseada em boas práticas de programação ou arquitetura, é só um teste da tecnologia. Há varios problemas sérios que teriam que ser refatorados para que a aplicação ficasse com um mínimo de decência com relação a boas práticas.

O projeto é feito com ASP.Net MVC, do zero, sem utilizar os templates do Visual Studio para cloud apps. Você cria uma aplicação ASP.Net MVC (fiz a minha já com o código do Release Candidate), faz umas referências a um código do Samples do CTP, outra para uma dll do Astoria, e já está habilitado para criar aplicações com Table Services do Azure.

O projeto tem duas entidades: canais (channels) e mensagens (messages). Elas são representadas por classes POCOs, não fosse por um atributo no nível da classe. É tudo que você precisa fazer para que a classe vá parar no Azure Table Storage.

Essa é a entidade de canais. Ela tem apenas 3 propriedades: PartitionKey, RowKey e DateCreated.

    [DataServiceKey("PartitionKey", "RowKey")]
    public class Channel
    {
        public string PartitionKey { get; set; }
        public string RowKey { get; set; }

        public DateTime DateCreated { get; set; }

        public Channel()
        {
        }

        public Channel(string name)
        {
            this.DateCreated = DateTime.UtcNow;
            this.PartitionKey = name;
            this.RowKey = string.Empty;
        }
    }

Essa é a entidade de Mensagens. Ela tem um método, chamado MakeKey que auxilia a cria a chave de partição (PartitionKey). Fora isso tem apenas 7 propriedades, sendo duas as obrigatórias PartitionKey e RowKey, e mais 5 bem simples:

    [DataServiceKey("PartitionKey", "RowKey")]
    public class Message
    {
        //channel name
        public string PartitionKey { get; set; }
        //datetime of creation
        public string RowKey { get; set; }

        public string Text { get; set; }
        public string Author { get; set; }
        public string Channel { get; set; }
        public DateTime DatePosted { get; set; }
        public int Rating { get; set; }

        public Message()
        {
        }

        public Message(string channel, string author, string text)
        {
            this.Text = text;
            this.Author = author;
            this.Channel = channel;
            this.DatePosted = DateTime.UtcNow;
            this.PartitionKey = MakeKey(channel, this.DatePosted);
            this.RowKey = System.Xml.XmlConvert.ToString(this.DatePosted,
                System.Xml.XmlDateTimeSerializationMode.Utc);            
        }

        public static string MakeKey(string channel, DateTime dt)
        {
            return channel + "@" + dt.ToString("yyyy-MM-dd");
        }
    }

Temos ainda uma classe chamada MicroData que é a responsável pelo contato com o Azure, e é um herdeiro do contexto do Astoria. Essa classe “TableStorageDataServiceContext” herda da classe “DataServiceContext” do Astoria. É a típica classe que ficaria escondida no repositório da aplicação.

    public class MicroData : TableStorageDataServiceContext
    {
        public IQueryable<Channel> Channels
        {
            get
            {
                return this.CreateQuery<Channel>("Channels");
            }
        }
        public IQueryable<Message> Messages
        {
            get
            {
                return this.CreateQuery<Message>("Messages");
            }
        }
    }

Com isso todo o contato com o Azure já pode ser feito. As iterações são feitas através do contexto (a classe MicroData). Tudo bem simples, você usa as propriedades que criou na classe MicroData para acessar as respectivas tabelas (propriedades “Channels” e “Messages”). Há também um código para criar as tabelas, mas não vou mostrar para não desviar do assunto. Pense que cada entidade tem uma tabela lá no Table Services.

Por exemplo, para recuperar canais:

            var svc = new Models.MicroData();
            ViewData["channels"] = svc.Channels;

Ou então com LINQ, recuperando mensagens:

var q = from m in svc.Messages 
        where m.Author == name 
        select m; 

ViewData["msg"] = q;

Para inserir dados também é bem simples. Abaixo o código para inserir uma mensagem.

            var svc = new Models.MicroData();
            var m = new Models.Message(channel, author, msg);
            svc.AddObject("Messages", m);
            svc.SaveChanges();

Se você já viu uma demo de Astoria, vai ver que não muda praticamente nada.

Você pode pegar o código completo dos meus testes aqui. Se você tem o ASP.Net MVC ele vai abrir normalmente, se você não tem… eu te pergunto: porque você ainda não tem?

Depois eu comento os detalhes da criação da infra para usar o com Azure assim como outros detalhes conceituais.

Giovanni Bassi

Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.