Entity Framework Core -  DBSet<T> ou Set<T> qual usar ?


Você sabe a diferença entre DBSet<T> e Set<T> e quando pode ou deve usar um ao invés do outro ?

A classe DbSet<TEntity> representa uma coleção para uma determinada entidade dentro do modelo e é a porta de entrada para as operações de banco de dados em uma entidade.

As classes DbSet<TEntity> são adicionadas como propriedades ao DbContext e são mapeadas por padrão para tabelas de banco de dados que levam o nome da propriedade DbSet<TEntity>. O DbSet é uma implementação do padrão Repository.

A seguir temos um exemplo de código que mostrar o uso do DBSet<TEntity>:

    public class AppDbContext : DbContext 
    {
        ...
       
        public DBSet<Cliente> Clientes { get; set; }   
        public DBSet<Pedido> Pedidos { get; set; } 
    }

Neste exemplo temos duas propriedades DBSet<TEntity> adicionadas à classe DbContext.

- A primeira representa uma coleção de objetos Cliente a qual é mapeada por convenção para a tabela 'Clientes' do banco de dados;
- A segunda propriedade DBSet representa uma coleção de objetos Pedido que é mapeado para a tabela 'Pedidos'.

Na documentação do EF Core encontramos que Set<TEntity> cria um DBSet<TEntity> que pode ser usado para consultar e salvar instâncias de TEntity.

Então qual a diferença entre Set<TEntity> e DBSet<TEntity> ?

Nenhuma. Eles fazem praticamente a mesma coisa.

A propriedade DbSet<TEntity> e o método Set<TEntity> são funcionalmente equivalentes, mas possuem algumas diferenças não funcionais.

As propriedades DbSet são preenchidas uma vez na criação do contexto, enquanto o método Set sempre executa uma pesquisa, portanto, o acesso à propriedade DbSet deve ser mais rápido que o método Set (embora não seja significativo).

Veja o código da consulta a seguir onde estamos obtendo todos os clientes:

            using (var db = new AppDbContext())
            {
                var blogs = db.Clientes.ToList();                                  
            }

Eu posso escrever esse código assim:

            using (var db = new AppDbContext())
            {
                var blogs = db.Set<Cliente>().ToList();                       
            }

A real questão é quando você deve usar Set<TEntity> e quando deve usar DSet<TEntity>.

Você usa o DbSet quando conhece o tipo de entidade com a qual deseja trabalhar.

Neste contexto, você simplesmente escreve o nome DbContext e, em seguida, o nome do tipo de entidade e pode criar, ler, atualizar ou excluir entradas para essa entidade com os métodos de entidade disponíveis. Você sabe o que quer e sabe onde fazê-lo.

Você usa Set quando não conhece o tipo de entidade com a qual deseja trabalhar.

Digamos que você deseja criar uma classe que funcione no seu repositório para criar, ler, atualizar e excluir entradas para uma entidade. Você deseja que esta classe seja reutilizável para que você possa passar um DbContext nela e ela usará os mesmos métodos de criação, leitura, atualização e exclusão.

Como você não sabe ao certo em qual DbContext ele será usado ou em que DbSet o DbContext terá , você vai criar um código genérico para que sua classe possa ser usada por qualquer DbContext para qualquer DbSet.

Portanto, embora você possa manter seu DbContext sem as propriedades expostas do DbSet e trabalhar apenas com o método Set, se você fizer isso, precisará informar explicitamente o EF Core quais são os tipos de entidade, adicionando ao OnModelCreating uma chamada para modelBuilder.Entity<TEntity>(); para cada tipo de entidade.

Para ficar claro veja o exemplo de código abaixo onde definimos um código genérico:.

public class Repository<TDbContext> where TDbContext : DbContext
{
    private TDbContext _context { get; }
    public Repository(TDbContext context)
    {
       _context = context;
    }
    public TEntity Create<TEntity>(TEntity entity) where TEntity : class
    {
        if(entity != null)
        {
            var dataSet = _context.Set<TEntity>();
            if(entity is IEnumerable)
            {
                dataSet.AddRange(entity);
            }
            else
            {
                dataSet.Add(entity);
            }
            _context.SaveChanges();
        }
        return entity;
    }
}

Aqui como temos um código genérico usamos _context.Set<TEntity>.

E estamos conversados...

"Fui buscado dos que não perguntavam por mim, fui achado daqueles que não me buscavam; a uma nação que não se chamava do meu nome eu disse: Eis-me aqui. Eis-me aqui."
Isaías 65:1

Referências:


José Carlos Macoratti