Não é incomum nossas aplicações trabalharem com armazenamento de dados. No mundo mobile, além de criarmos um banco de dados “temporário” localmente nos dispositivos, utlizando desde soluções SQL como SQLITE até soluções NO SQL como o LITE DB , também criamos uma API que irá receber os dados mais importantes e sensíveis da aplicação.

Vale ressaltar que por motivos de segurança, principalmente no mundo mobile, não é recomendado que as aplicações se conectem diretamente com o banco de dados master para salvar / consultar informações. Como nós já sabemos, as conexões mobile sofrem com uma qualidade não tão boa como desejada, ficando a mercêr de 3Gs e alance de WiFis.

O que é o Cosmos DB

Cosmos DB é um serviço de banco de dados multi modelo e distribuido globalmente. É um serviço desenvolvido pela Microsoft e está disponível no Azure.

Apesar de ser um banco de dados não racional e baseado em documentos, ele possui diversas linguagens de manipulação como o próprio SQL. O Cosmos DB possui SDKs para integração com .NET, Java, JavaScript, Phyton, C++, Gremlin, GO e Xamarin.

Você pode ver alguns quick starts neste endereço.

Porque usar o Cosmos DB?

O Cosmos DB oferece algumas vantagens bastante interessantes para nossas aplicações como:

Escalabilidade global: Imagine  que você criou um banco de dados para sua aplicação no Brasil e com o decorrer do tempo, percebe que sua aplicação passou a ser utilizada também por pessoas que moram no Estados Unidos. Sem problemas, com alguns cliques você consegue replicar a sua base dados para um datacenter do Azure no Estados Unidos e os usuário de lá passarão a utilizar este banco da dados, diminuindo a latência do serviço.

Segurança: Toda comunicação do Cosmos DB é feita encima de HTTPS, suas informações são criptografadas ao sair da sua aplicação até chegarem ao servidor e vice versa. É comum termos problemas de conexão no mundo mobile, como citei acima. A comunicação do Cosmos DB é executa com um three-way Handshake, ou seja, o pacote sai da sua aplicação, chega ao Cosmos DB que por sua vez envia uma confirmação de recebimento para aplicação e então a aplicação envia uma confirmação do recebimento deste pacote de confirmação para o Cosmos DB.

RestFull APIs: Todas as iterações são feitas com o protocolo HTTP. Você pode utilizar todos os recurso do protocolo como por exemplo os Status Code na resposta de cada requisição.

Além destes pontos citados acima, o custo do Cosmos também é bem interessante sendo R$ 0,83 centavos por giga de armazenamento mensais.

Como posso manipular os dados salvos no Cosmos DB?

Como eu citei acima, ele possui SDKs de integração com  .NET, Java, JavaScript, Phyton, C++, Gremlin, GO e Xamarin. Além disto, você pode acessar o portal do Azure e utilizar a linguagem escolhida por você no momento da criação para manipular os dados, além de ser possível utilizar também o Azure Storage Explorer.

Na criação do seu banco de dados Cosmos DB você poderá optar por algumas APIs de manipulação de dados, atualmente as disponíveis são:

  • SQL API
  • MongoDB API
  • Cassandra API
  • Graph API
  • Table API

Você pode escolher a que você possui maior familiaridade para utilizar na manipulação dos documentos salvos no seu banco de dados.

Criando o banco de dados no Cosmos DB

Acesse o portal do Azure e selecione a opção Azure Cosmos DB e então clique em + Add

Preencha as informações solicitadas e selecione a API de manipulação de dados de sua preferencia na caixa de seleção API e clique em Create. Neste exemplo, vou trabalhar com a opção de API SQL.

criação-cosmosdb

 

Após ser finalizado o deploy do Azure Cosmos DB ele estará disponível na sua conta no resource group selecionado.

Escalabilidade Global

Acessando o menu Replicate data globally você irá visualizar a região do data center que selecionou na criação e os demais que estão disponíveis para replicação global do banco de dados. Lembre-se que cada replicação implicará em aumento de custos, então só faça isto em caso de necessidade.

escalabilidade-global

Chaves para somente leitura e para leitura e escrita

Acessando o menu Keys você irá visualizar as chaves de acesso para o banco de dados. Por padrão o Cosmos DB já possui duas chaves de acesso, um com diretos apenas de leitura e outra para leitura e escrita.

chaves

Cada unidade de armazenamento de dados no Cosmos DB é uma Collection. Dentro das collections serão armazenados nosso documentos que conterão nossos dados.

Clicando na opção Settings, você terá acesso ao painel de criação e gerenciamento das collections. Clicando na opção New Collection você poderá criar uma nova collection. Clicando na opção New SQL Query você poderá utilizar a linguagem SQL para consultar os dados da sua collection

scale

 

Xamarin Forms + Cosmos DB

A integração entre Xamarin e o Cosmos DB é bastante simples, dado que a ferramenta já disponibiliza um SDK para integração.

Nos passos a seguir vou falar sobre a integração entre o app e o Cosmos DB, para não alongar muito o artigo não vou falar sobre as configurações do projeto para ViewModels como PropertyChanged e Bindings. Você poderá ver isto no código fonte do post que está no GitHub disponível no link no final do artigo.

Após criado o Cosmos DB e a collection no portal do Azure, já podemos iniciar a integração entre o app e o serviço de banco de dados. Para isto, vamos iniciar instalando o SDK para .NET

Instale o pacote do NuGet Microsoft.Azure.DocumentDB.Core no PCL e em todas as plataformas

Install-Package Microsoft.Azure.DocumentDB.Core

Usando as keys de leitura e escrita e apenas leitura

Vamos criar uma classe estática para armazenar nossas keys e também a URL do nosso serviço Cosmos DB criados anteriormente no portal do Azure:

    public static class DocumentDbConstants
    {
        public static readonly string ReadWritePrimaryKey = "Sua chave de leitura e escrita gerada no azure";
        public static readonly string ReadOnlyPrimaryKey = "Sua chave somente leitura gerada no azure";

        public static readonly string Url = "url do Cosmos DB gerado no azure";
    }

Criando uma tela de listagem de dados

Após criada a classe que irá conter nossas constantes, vamos criar uma tela de lista para exibir os registros salvos no Cosmos DB

   <ContentPage.ToolbarItems>
        <ToolbarItem Text="Add" Command="{Binding AddClubCmd}"/>
    </ContentPage.ToolbarItems>
    <ContentPage.Content>
        <StackLayout>
            <ListView ItemsSource="{Binding Clubs}" HasUnevenRows="True">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <StackLayout HeightRequest="60" Padding="10">
                                <Label Text="{Binding Name}" FontSize="16" FontAttributes="Bold"/>
                                <Label Text="{Binding Country}"/>
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>

Vamos também criar uma ViewModel para esta tela que irá realizar a consulta de dados no Cosmos DB chamada ClubListViewModel.

Na ViewModel vamos criar um objeto do tipo DocumentClient, que estará disponível após a importanção da biblioteca Microsoft.Azure.Documents.Client do SDK, chamado client. Através deste objeto faremos as iterações com o Cosmos DB. Vamos também criar uma propriedade do tipo URI chamada collectionLink que irá apontar para nossa unidade de dados e para a Collection do Cosmos DB no Azure, recebendo o valor gerado pelo o método CreateDocumentCollectionUri do classe UriFactory do SDK.

 
private DocumentClient client; 
private Uri collectionLink = UriFactory.CreateDocumentCollectionUri(@"SampleCosmos", @"Clubs"); 

Onde SampleCosmos é o nome da unidade de armazenamento de dados e Clubs é o nome da collection.

Vamos instanciar nosso client no método construtor da ViewModel e utilizar as constantes definidas na classe DocumentDbConstants criada acima:

client = new DocumentClient(new System.Uri(DocumentDbConstants.Url), DocumentDbConstants.ReadOnlyPrimaryKey);

Observe que como o intuito desta página é apenas listar dados, além da URL do Cosmos DB, vamos informar a chave de apenas leitura para nosso client.

Além disto, teremos também uma lista para receber os dados, um command irá chamar o método que irá realizar a consulta no Cosmos DB.

Consultado dados no Cosmos DB

O método abaixo irá consultar todos os registros da collection no Cosmos DB. Observe que vamos utilizar a collectionLink que foi definida na ViewModel

        public async Task GetAll()
        {
            try
            {
                var query = client.CreateDocumentQuery<Club>(collectionLink, new FeedOptions { MaxItemCount = -1 })
                      .AsDocumentQuery();
                while (query.HasMoreResults)
                {
                    Clubs.AddRange(await query.ExecuteNextAsync<Club>());
                }
            }
            catch (Exception e)
            {
                Console.Error.WriteLine(@"ERROR {0}", e.Message);
            }
            
        }

Criando a tela de inserção de dados

Vamos adicionar uma nova página que deve ser exibida quando o usuário clicar no menu add da barra de titulo da tela de lista:

        <StackLayout>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>

                <Label Text="Club Name: " Grid.Column="0" Grid.Row="0"/>
            
                <Entry Placeholder="Club Name" Text="{Binding NewClub.Name}" Grid.Column="1" Grid.Row="0"/>

                <Label Text="Country: " Grid.Column="0" Grid.Row="1"/>

                <Entry Placeholder="Country" Text="{Binding NewClub.Country}" Grid.Column="1" Grid.Row="1"/>

            </Grid>
            <Button Text="Save" Command="{Binding SaveCmd}"/>
        </StackLayout>

Assim como na ViewModel da página de lista, nesta página também vamos adicionar os objetos clientcollectionLink

Você pode isolar estas operações em um Service de forma genérica para que centralize as comunições com o Cosmos DB no service. Para efeitos didáticos manterei na ViewModel.

Nesta ViewModel, como o objetivo é inserir dados, vamos informar para o client além da URL do Cosmos DB a chave de leitura e escrita no Cosmos DB que está armazenado na classe DocumentDbConstants, veja abaixo:

client = new DocumentClient(new System.Uri(DocumentDbConstants.Url), DocumentDbConstants.ReadWritePrimaryKey);

Inserindo dados no Cosmos DB

O método abaixo irá inserir dados no Cosmos DB. Observe que a comunicação entre app e Cosmos DB será realizada encima do protocolo HTTPS, sendo possível checar o StatusCode da requisição. Isto é importante pois assim temos a certeza de que o banco de dados recebeu o comando por completo, previnindo assim que o banco fique corrompido por problemas de conexão do smartphone que está executando a app. Para garantir que o pacote foi recebido com sucesso e integro pelo Cosmos DB ocorre um troca de pacotes de confirmação automatica entre app e Cosmos DB. Assim que o Cosmos DB recebe o pacote ele emite uma mensagem de confirmação para o app que ao receber este pacote envia outro confirmando o recebimento do anterior.

        public async Task InsertItemAsync(Club club)
        {
            try
            {
                club.Id = Guid.NewGuid().ToString();

                var result = await client.CreateDocumentAsync(collectionLink, club);

                if(result.StatusCode == System.Net.HttpStatusCode.OK)
                    await App.Current.MainPage.Navigation.PushAsync(new Views.ClubList());
                
            }
            catch (Exception e)
            {
                Console.Error.WriteLine(@"ERROR {0}", e.Message);
            }
        }

No método acima checamos se o StatusCode recebido é o 200 do protocolo HTTP e se for redirecionamos para  página de lista.

Com base no StatusCode poderiamos tomar diferentes ações para cada código de resposta do HTTP, como 400, 401, 500 entre outros.

Conclusão

Como podemos ver no decorrer do post, o Cosmos DB possui muitos recursos para nossas aplicações, desde chaves de segurança com niveis de permissões distintos a escalabilidade global geoposicional, até mesmo a possibilidade de trabalhar com SQL sendo um banco de dados não relacional. Não é possivel dizer que com o Cosmos DB você não precisará mais de uma API no seu app. Sabemos que cada aplicação possui cenários diferentes de complexidade. Entretando, se o seu cenário for apenas de CRUD simples acredito que o Cosmos DB poderá de te ajudar bastante reduzindo a necessidade de uma API para integração com app.

E ai o que você acha? Concorda? Já fez algo com o Cosmos DB?

 

Você pode efetuar o download do codigo fonte do post no meu GitHub clicando aqui

(Cross-post de hhttp://rsamorim.azurewebsites.net/2018/04/03/xamarin-forms-e-azure-cosmosdb/)