Cell CMS — Persistindo Dados
Tags: api, entityframework, csharp, development
Published: 2020-06-24 23:58:43

---
title: Cell CMS — Persistindo Dados
published: true
date: 2020-03-24 16:01:02 UTC
tags: api,entityframework,csharp,development
canonical_url: 
series: CellCms
---

### Cell CMS — Persistindo Dados

![](https://cdn-images-1.medium.com/max/1024/0*WP25hjnwqwH_ojEa)<figcaption>Photo by <a href="https://unsplash.com/@anniespratt?utm_source=medium&amp;utm_medium=referral">Annie Spratt</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption>

No [último post](https://dev.to/ardc_overflow/cell-cms-autenticando-o-admin-25kn-temp-slug-221933) preparamos a nossa autenticação! Agora é hora de começarmos a pensar em como vamos armazenar os dados deste usuário.

A arquitetura inicial previa que apenas um usuário utilizaria o sistema para publicar conteúdos, _o Administrador_, porém como utilizamos o Azure AD para autenticar podemos acabar em situações em que mais de um usuário tem acesso ao App.

Por enquanto vamos pensar em um cenário **sem separação de usuários**. Ou seja, **se a pessoa esta autenticada** no Active Directory ela terá acesso a  **tudo.**

> “Ah Rodolpho, mas como vamos impedir de alguém fazer login no nosso App então e acabar com nossos dados!?”

Lembram de um comentário que coloquei nas configurações do Token no Post Anterior? **Futuramente vamos alterar** o TokenValidationParameters **para validar** o Issuer do Token com base nos **Tenants** que esperamos que tenha acesso ao App! Essa configuração poderá ser alterada em tempo de execução, seja por ambiente ou appsettings.json , permitindo que _deploys_ diferentes **validem contra Tenants diferentes.**

**Planejando e modelando nossos dados**

Tudo que for feito para este post estará no commit de merge do branch feature/models-persistencia, então bora conversar sobre dados! Pensando numa versão inicial pensei em três entidades básicas:

1. **Feeds** : Serão os “canais” onde publicaremos os conteúdos. A ideia aqui é que, numa aplicação futura, consigamos apontar para um Feed próprio dessa aplicação!
2. **Tags ou Labels** : Serão “marcadores” dentro de um Feed. A ideia é permitir algum nível de filtro, pelo usuário final, _dentro de um feed_.
3. **Content:** Será o conteúdo, propriamente dito. Uma entidade contendo ID, _relação com Tags, pertencendo a um feed_ e possuindo um **textão markdown**

![](https://cdn-images-1.medium.com/max/595/1*5Q6U3n5Kgh0-ri5JrP9RRQ.png)<figcaption>Diagrama com rascunho das entidades</figcaption>

Ou seja, temos os seguintes relacionamentos:

1. _um_ **Feed** _contém várias_ **Tags ** (1:N)
2. _um_ **Feed** _contém vários_ **Contents ** (1:N)
3. _um_ **Content** _possui várias_ **Tags** , _uma_ **Tag** _possui vários_ **Contents ** (N:N)

Nada cabeludo até agora. O relacionamento N:N dará um pouco mais de trabalho, mas nada absurdo! Hora de partimos para o código! Abra seu **Visual Studio,** crie uma nova pasta Models na Api e quatro novas classes para nossos objetos!

Sim, isso mesmo, **quatro** classes. Para implementarmos **um relacionamento N:N com o EntityFrameworkCore**  **precisamos decompor o relacionamento em dois relacionamentos 1:N**. Mais informações estão disponíveis na [documentação](https://entityframeworkcore.com/model-relationships#many-to-many-relationship)do EntityFrameworkCore.

Vamos às classes:

{% gist https://gist.github.com/rodolphocastro/7f29eca87073ed20fd4a58a58cc15263 %}

Criadas as classes, vamos para o **EntityFrameworkCore!**

**Instalando dependências**

Instale os seguintes pacotes **NuGet** em sua API **:**

1. **Microsoft.EntityFrameworkCore** : A principal biblioteca do EFCore.
2. **Microsoft.EntityFrameworkCore.Sqlite** : A biblioteca contendo suporte para utilizarmos o SQLite.
3. **Microsoft.EntityFrameworkCore.Design:** Biblioteca para a geração de Migrations

Além disso, abra seu **terminal** e instale a ferramenta do **EntityFrameworkCore** para **dotnet:**  **dotnet tool install --global dotnet-ef**. Tudo pronto? Vamos a **alguns conceitos** do  **EFCore:**

> O **EntityFrameworkCore** é um **ORM** (Object-Relational Mapper) que permite que mapeamos **Objetos** para **Dados Relacionais,** fazendo com que não seja necessário escrever uma camada para Acesso aos Dados em nossas Aplicações [[fonte](https://docs.microsoft.com/en-us/aspnet/entity-framework)]

> **Migrations** são o meio pelo qual o EntityFramework **garante** que os **Modelos** (classes) **sejam sincronizados com** os **Schemas** do Banco de Dados. Desta maneira, alterações nas classes (como adicionar um novo campo) são refletidas no banco (através da adição de uma nova coluna) e são versionadas junto ao código.

> As **configurações das entidades** , que serão refletidas no banco, **podem ser realizadas através de DataAnnotations** ou pela **FluentApi**. O **EntityFramework tentará** , por convenções, **aplicar configurações automáticas** , porém é **boa prática escrevermos nossas próprias configurações**.

O **EntityFramework** é uma biblioteca bem vasta então recomendo ir consultando a [documentação oficial](https://docs.microsoft.com/en-us/ef/core/) conforme novos requisitos forem surgindo! Além do bom e velho _StackOverflow!_

**Configurando os Models**

Vamos começar a escrever as configurações de nossas entidades. Para isso, crie uma nova pasta na API chamada **“Persistence”** e vamos criar 3 novas classes:

1. **FeedConfiguration**
2. **TagConfiguration**
3. **ContentConfiguration**
4. **ContentTagConfiguration**

Agora vamos escrever o código para que **estas classes realizem a configuração** de nossos **Models**. Para isso precisamos implementar, em cada uma delas, a interface IEntityTypeConfiguration<T> substituindo T pelo Model que será configurado! Feito isso, implemente o método Configure e utilize o builder para montar as configurações, como abaixo:

{% gist https://gist.github.com/rodolphocastro/5b74baf638ab509536e16e7075eb33f6 %}

Com as entidades configuradas agora devemos montar o nosso **Context.** A ideia aqui é **criar um único ponto para acesso aos Dados** controlados pelo **EntityFramework.** Na raiz da Api crie uma nova classe CellContext , ela deverá herdar o DbContext e terá algumas **propriedades para expor as tabelas** de nossos Models:

{% gist https://gist.github.com/rodolphocastro/cb66a9d8a6a11366886e801755a47d8b %}

Agora basta **adicionarmos o Context aos Services** e podemos partir para gerar as **Migrations** :

{% gist https://gist.github.com/rodolphocastro/8c0c71717027119805cbbaf8983c9094 %}

**Criando e Aplicando Migrations**

Antes de tudo **precisamos compilar a API**. Para isso execute dotnet build ou utilize os menus do VisualStudio e garanta que seus appsettings.json contem uma **ConnectionString válida** para o context a ser migrado!

> Se o projeto não estiver compilado ou se estiver sem uma ConnectionString válida e um Context acessível o EntityFramework não conseguirá gerar as Migrations!

Agora abra seu terminal de preferência e execute dotnet ef migrations add InitialCreate -o Persistence/Migrations para **criar as Migrations** iniciais do projeto com o nome **InitialCreate** e colocando na pasta Persistence/Migrations:

![](https://cdn-images-1.medium.com/max/1024/1*8nY8GzpGH_cvtA-zUyI3BA.gif)<figcaption>Gerando as migrations</figcaption>

**Serão gerados dois arquivos** : Um **Snapshot** e um “ **InitialCreate** ”. Um deles é a _Migration_, **que diz quais passos devem ser realizados para atualizar** ou desatualizar **a base** e o outro é uma “Captura” do status esperado que a base fique após aplicação de todas as Migrations.

![](https://cdn-images-1.medium.com/max/661/1*4y4fiXfjzejnMce1MVvLpg.png)

![](https://cdn-images-1.medium.com/max/596/1*26Iogkv-F0ecy-RNe4cM0A.png)<figcaption>Exemplos de Migration e Snapshot</figcaption>

Finalmente, vamos voltar ao terminal e gerar a nossa base de dados! Digite o comando dotnet ef database update para que o EntityFramework, com base em sua ConnectionString, **atualize a base de dados** _(como ainda não temos uma base, ele irá criar a base para nós!)_

![](https://cdn-images-1.medium.com/max/1024/1*hZEP8X1A9QYWY8I7i-fMzQ.gif)<figcaption>Criando a base de dados</figcaption>

**Como realizar deploy da base de dados**

Um assunto que sempre gera controvérsias com os usuários do EntityFramework é qual a maneira correta de aplicar as Migrations a uma base de Produção. Afinal, temos várias maneiras de fazer isso:

1. Através da ferramenta dotnet ef
2. Através de Scripts SQL gerados pela ferramenta
3. Através do próprio sistema

Pessoalmente eu sou fã da alternativa **3 — Através do próprio sistema.** Acredito que **no cenário atual** com _Containers_, _Kubernetes_ e tudo ficar **gerando scripts** para um dba **aplicar manualmente** é **muita mão de obra** e vai contra a ideia de termos _Entregas_ e _Integrações Contínuas_. Obviamente que isso não é verdade para todos os casos, mas sempre que possível sigo por esta linha.

Minha maneira favorita para realizar esta tarefa é:

- **Utilizar uma flag** , de ambiente, **para indicar** que a rotina de **migração automática** deve ser realizada
- **Extender** o IHost para **verificar esta flag** e verificar se existem Migrations pendentes
- **Se houver Migrations pendentes** : **Tentar** , até um limite de vezes, **atualizar a base**.

O Snippet abaixo realiza todos estes passos, utilizando a biblioteca **Polly** para o controle de tentativas, a qual eventualmente abordarei em um post separado por ser extremamente flexível e útil:

{% gist https://gist.github.com/rodolphocastro/a51666de36f9dd328676ae48a064a8ba %}

Para maiores informações dê uma olhada nestes links:

- [https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli)
- [https://github.com/dotnet/efcore/issues/5096](https://github.com/dotnet/efcore/issues/5096)
- [https://stackoverflow.com/questions/48617880/ef-core-migrations-in-docker-container](https://stackoverflow.com/questions/48617880/ef-core-migrations-in-docker-container)
- [https://github.com/dotnet/EntityFramework.Docs/issues/814](https://github.com/dotnet/EntityFramework.Docs/issues/814)

**Considerações Finais**

Terminamos o post de hoje por aqui! O assunto EntityFrameworkCore é muito abrangente e poderiamos perder horas e horas falando sobre ele, porém a ideia aqui é dar uma pincelada e permitir que você saia daqui com um “norte” a seguir!

Como sempre tudo que foi realizado durante este post estará disponível no repositório do [Cell CMS](https://github.com/rodolphocastro/cell-cms), em específico no merge do branch feature/models-persistencia!

Obrigado por lerem até aqui e até o próximo post! Abraços!