Hoje veremos como podemos criar e trabalhar com entidades sem chaves usando o EF Core. |
Às vezes, podemos precisar declarar entidades usando o EF Core que não possuem chaves primárias. Neste artigo, vamos entender por que tais entidades seriam necessárias e como defini-las.
Quando qualquer modelo do EF core é definido, por padrão, o EF core marca uma
propriedade como chave primária. Uma propriedade pode ser declarada como chave
primária decorando-a com o atributo [Key] ou via
Fluent API usando o método
HasKey.
Se não for especificado explicitamente, o EF Core verifica se existe uma
propriedade com o nome “Id” ou {EntityName}Id, e,
se houver tal propriedade, ela será marcada por padrão como chave primária
para a entidade.
Se não houver tal propriedade, o EF core lançará um erro do tipo:
O tipo de entidade '{EntityName}' requer que uma
chave primária seja definida. Se você pretendia usar um tipo de entidade sem
chave, chame ‘HasNoKey’ em ‘OnModelCreating’.
O erro está pedindo para definir uma chave primária no modelo.
Mas e se não quisermos ?
Como conseguir isso ?
Bem, a resposta está na própria mensagem
de erro. Mas antes de analisar a sintaxe, vamos primeiro ver onde as entidades
sem chave seriam necessárias.
Por que você precisaria de uma entidade sem chave primária ?
Entidades sem chave podem ser necessárias se o esquema do banco de dados contiver uma tabela ou View sem nenhuma chave primária.
Nesses casos, essa tabela ou
View pode ser mapeada para uma entidade sem chave.
Às vezes, entidades sem chave também podem ser usadas para mapear resultados de
um SQL bruto.
Como podemos definir isso ?
Existem duas maneiras de definir uma entidade sem chave :
Quando uma entidade é definida como entidade sem chave, ela não pode conter uma chave primária. Portanto, nunca pode ser uma entidade principal, pois não possui uma chave. Além disso, as entidades sem chave não são rastreadas pelo DbContext.
O trecho de código abaixo mostra como usar o atributo DataAnnotation [Keyless] para marcar uma entidade "Aluno" como sem chave.
using Microsoft.EntityFrameworkCore;
[Keyless]
public string? Email { get; set; } public string? Telefone { get; set; } public DateTime? Nascimento { get; set; } |
A seguir a mesma entidade sendo definida com sem chave usando a API fluente :
public class AppDbContext : DbContext { public AppDbContext(DbContextOptions<AppDbContext> opt): base(opt) {} public DbSet<Product>? Products { get; set; } public DbSet<Aluno>? Alunos { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) |
Uma as formas de usar uma entidade sem chave em consultas é usar o método DbSet<T>.FromSqlInterpolated() e escrever uma consulta SQL que selecione as colunas da entidade sem chave.
Para uma entidade Products com Name, Amount podemos definir a consulta:
var products =
context.Set<Products>() .FromSqlInterpolated($"SELECT TOP 10 Name, SUM(Amount) as Total FROM Products GROUP BY Name ORDER BY Total DESC") .ToList(); |
Características das entidades sem chave
Os tipos de entidade sem chave suportam
muitos dos mesmos recursos de mapeamento que os tipos de entidade regulares,
como mapeamento de herança e propriedades de navegação. Em armazenamentos
relacionais, eles podem configurar os objetos e colunas do banco de dados de
destino por meio de métodos de API fluentes ou anotações de dados.
No entanto, eles são diferentes dos tipos de entidade regulares, da seguinte
forma:
No entanto podemos usar essas entidades nos seguintes contextos:
Nota: Para mapear uma entidade sem chave para um objeto de banco de dados usando a Fluent API usamos os métodos ToTable e ToView.
"Estejam
vigilantes, mantenham-se firmes na fé, sejam homens de coragem, sejam
fortes."
1 Coríntios 16:13
Referências: