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)
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.
.UseIdentityAlwaysColumn();
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.
Obrigado
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.
Top comments (0)