Como trabalhar com Postgres SQL e NOSql juntos com Entity Framework Core?
Tags: postgres, entityframeworkcore, csharp, programming
Published: 2021-12-14 03:38:39

[This topic in English](https://dev.to/mgpaixao/how-to-use-postgres-sql-nsql-and-entity-framework-core-804)


![Gif](https://media.giphy.com/media/xT9IgG50Fb7Mi0prBC/giphy.gif)

Olá. Vou mostrar um passo a passo de como trabalhar com banco de dado relacional e não relacional ao mesmo tempo com Postgres e suporte para EFCore.

#Postgres


Postgres é uma banco de dados objeto-relational que pertence a empresa Oracle, porém é um banco de dados open source com uma forte comunidade mantendo-o. Postgres é incrivelmente robusto e confiável, dado seu histórico de 30 anos no mercado.


#Data Types


Primitives: Integer, Numeric, String, Boolean
Structured: Date/Time, Array, Range / Multirange, UUID
Document: JSON/JSONB, XML, Key-value (Hstore)
Geometry: Point, Line, Circle, Polygon
Customizations: Composite, Custom Types


#JSON/JSONB - Trabalhando com NSql


Uma das maravilhas do banco de Postgres é a possibilidade de trabalhar de forma relacional e não relacional no mesmo banco, no mesmo objeto, na mesma tabela. SIM ! É possível, através do tipo de dado Document, que recebe dados Json e JsonBinary (JsonB).

#Entity FrameWork Core ORM


Para podermos usar o EFcore nos nossos métodos usando o NSql, precisamos instalar um pacote nuget chamado `npgsql.entityframeworkcore.postgresql` ele vai permitir fazer os métodos CRUD de forma mais parecida com o EFCore ORM que estamos acostumados.

#Prática - Configuração


###Pacotes


`npgsql.entityframeworkcore.postgresql
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.Toll
EFCore.NamingConventions`


#StartUp

`ConfigureServices Method`
```
            services.AddDbContext<PostgresNsql.MyContext>(option => option.UseNpgsql(Configuration.GetConnectionString("Nsql")));

```


#DBContext

```
public class MyContext : DbContext
    {
        public MyContext(DbContextOptions options) :base(options)
        {

        }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            => optionsBuilder
            .UseNpgsql()
            .UseSnakeCaseNamingConvention();

        protected override void OnModelCreating(ModelBuilder modelBuilder)
            => modelBuilder
            .Entity<DataModel>()
            .Property(e => e.Id)
            .UseIdentityAlwaysColumn();

        public DbSet<DataModel> DataModels { get; set; }
    }
```

`UseSnakeCaseNamingConvention()` Snake Case pode ser necessário para lidar com JSONs que separam 2 palavras com _ underline. Dessa forma não tera problemas com serialização.


Definindo auto-increment na coluna ID
`.Property(e => e.Id)
 .UseIdentityAlwaysColumn();` Identity always column é um dos tipos de atribuição de valor que você pode dar, nessa modalidade você define que os valores serão gerados diretamente no banco, impossibilitando você setar o valor no momento de inserção no banco de dados.

#Model


Na criação da model é que está o grande pulo do gato no uso de SQL e NSql juntos. Caso você tenha dados instáveis ainda e eles não são 100% mapeaveis e estruturados, você pode usar o DataType Json para receber a parte NSql dos seus dados.


Para isso, você precisa adicionar a biblioteca `System.Text.Json` e tipar a sua propriedade com a classe JsonDocument, pois ele já identificará que ali será recebido dados em JSON e facilitará a descerialização.


A model precisa ser IDisposable pois a classe JsonDocument é IDisposable também, melhorando o gerenciamento de memória. 

```
public class DataModel : IDisposable
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public int idade { get; set; }

        public JsonDocument Data { get; set; }

        public void Dispose() => Data?.Dispose();
    }
```


#Dados Estruturados


Para identificar a parte NSql da nossa model, é preciso adicionar a Data Notation `[Column(TypeName = "jsonb")]` para identificar o objeto Json e mapear as propriedades.


```
public class DataModel
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public int idade { get; set; }

        [Column(TypeName = "jsonb")]
        public Endereco Address { get; set; }
    }

public class Endereco // Mapeando os dados recebidos em Json
{
    public string Rua { get; set; }
    public int Numero { get; set; }
    public Casa[] Casas { get; set; }
}

public class Casa 
{
    public decimal Preco { get; set; }
    public string EnderecoCompleto { get; set; }
}
```


#CRUD


Eu não usei um repositório ou alguma arquitetura mais complexa para facilitar o entendimento do artigo.

Mas mostrarei agora na Controller como podemos trabalhar com os dados do tipo JSON.

#GetAll()
Percebam que nada muda na listagem de todas as colunas.

```
public List<DataModel> GetAll()
        {
            return _myContext.DataModels.ToList();
        }
```


#GetPersonalidado


Uma dúvida que tinha quando começando a trabalhar com Postgres SQL e NSql junto é se dava pra fazer em uma consulta, juntar os dados SQL e NSql. Abaixo está um exemplo de um Get onde eu parametrizo que quero apenas resultados de pessoas com 12 anos E com o ultimo nome igual a "Paixao". Idade é um valor SQL da coluna idade e "lastname" é um item dos dados que recebemos em JSON. 


```
public IEnumerable<string> Get()
        {
            var resultado = _myContext.DataModels;

            return resultado.Where(x => x.idade == 12 && x.Data.RootElement.GetProperty("lastName").GetString() == "Paixao").ToList();           
        }
```

Um outro exemplo que trouxe, é caso você quero exibir apenas 1 dos itens dos dados em JSON.

```
public IEnumerable<string> Get()
        {
            var resultado = _myContext.DataModels;

return resultado.Select(x=>x.Data.RootElement.GetProperty("lastName").GetString()).ToList();
        }
```

##Elementos da classe JsonElement do código apresentado acima
`RootElement` é uma classe que vai pegar os dados JSON da propriedade `Data` permitindo que você então denomine com o método `GetProperty("propriedade")` qual propriedade do JSON você vai trabalhar e por final você deve colocar o método `GetString()` para converter o dados JSON que você filtrou em string. 
 

![Gif](https://media.giphy.com/media/d68IdpvmAHohx5NMEV/giphy.gif)

Obrigado
{% user mgpaixao %}


![linha horizontal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n8bndcx2jkn1jz1dy98v.png)
### Disclaimer

A VaiVoa incentiva seus Desenvolvedores em seu processo de crescimento e aceleração técnica. Os artigos publicados não traduzem a opinião da VaiVoa. A publicação obedece ao propósito de estimular o debate.

![logo vaivoa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1wmziqv74ghhgyi9p0om.png)