DEV Community 👩‍💻👨‍💻

Cover image for Como trabalhar com Postgres SQL e NOSql juntos com Entity Framework Core?
Matheus Paixão
Matheus Paixão

Posted on • Updated on

Como trabalhar com Postgres SQL e NOSql juntos com Entity Framework Core?

This topic in English

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")));

Enter fullscreen mode Exit fullscreen mode

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; }
    }
Enter fullscreen mode Exit fullscreen mode

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();
    }
Enter fullscreen mode Exit fullscreen mode

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; }
}
Enter fullscreen mode Exit fullscreen mode

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();
        }
Enter fullscreen mode Exit fullscreen mode

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();           
        }
Enter fullscreen mode Exit fullscreen mode

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();
        }
Enter fullscreen mode Exit fullscreen mode

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

Obrigado

mgpaixao image

linha horizontal

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

Top comments (0)

DEV

Thank you.

 
Thanks for visiting DEV, we’ve worked really hard to cultivate this great community and would love to have you join us. If you’d like to create an account, you can sign up here.