> ## Content Index
> Fetch the complete content index at: https://www.azurebrasil.cloud/llms.txt
> Use this file to discover other available public pages before exploring further.

# Trabalhando com Views de banco de dados no EF Core
- URL: https://www.azurebrasil.cloud/blog/trabalhando-com-views-no-ef/
- Published: 2024-05-10T13:07:48.000Z
- Updated: 2024-05-10T13:07:48.000Z
- Author: Talles Valiatti

O[ Entity Framework Core](https://learn.microsoft.com/pt-br/ef/core/?ref=azurebrasil.cloud) é um framework ORM (Object-Relational Mapper) que facilita o acesso e a manipulação de dados em bancos de dados relacionais a partir de código [.NET](https://dotnet.microsoft.com/pt-br/?ref=azurebrasil.cloud). Uma das características poderosas do EF Core é sua capacidade de [mapear entidades de banco de dados para classes .NET e vice-versa](https://learn.microsoft.com/en-us/ef/core/modeling/entity-types?tabs=data-annotations&ref=azurebrasil.cloud).

Neste artigo, vamos explorar a integração das [views do banco de dados](https://learn.microsoft.com/en-us/sql/relational-databases/views/views?view=sql-server-ver16&ref=azurebrasil.cloud) diretamente no código-fonte das nossas aplicações, utilizando as [migrações](https://learn.microsoft.com/pt-br/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli&ref=azurebrasil.cloud). Essa abordagem pode ser uma estratégia eficaz para evitar a necessidade de [versionar](https://git-scm.com/?ref=azurebrasil.cloud) as views separadamente do código-fonte, simplificando assim o processo de desenvolvimento e manutenção.

Vamos criar inicialmente um diretório para o nosso projeto: 

```
mkdir EfCoreViews
```

Como iremos fazer uma integração com o EF Core, subiremos um banco de dados por meio de um [*docker compose*](https://docs.docker.com/compose/?ref=azurebrasil.cloud).

````
version: '3.8'
services:
  database:
    container_name: "sqlserver"
    hostname: "sqlserver"
    ports:
      - "1433:1433"
    image: "mcr.microsoft.com/azure-sql-edge:latest"
    environment:
      ACCEPT_EULA: "1"
      MSSQL_SA_PASSWORD: "Teste12345!"
    
```

Vamos ainda criar o versionamento via [*git*](https://git-scm.com/?ref=azurebrasil.cloud) no diretório raiz.

```
dotnet new gitignore
git init
```

Com as dependências prontas, já podemos criar o projeto do tipo [console](https://learn.microsoft.com/pt-br/dotnet/core/tutorials/with-visual-studio?pivots=dotnet-8-0&ref=azurebrasil.cloud) e adicionar alguns pacotes NuGet a esse projeto criado.

````
dotnet new console
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Design
```

A ideia desse post é criar um pequeno projeto que utiliza views para simplificar as [*queries*](https://learn.microsoft.com/pt-br/ef/core/querying/?ref=azurebrasil.cloud)*.* Por isso, vamos criar uma modelagem simples de dados: Iremos ter uma entidade chamada *Author*[ que possui uma lista de *Books*](https://learn.microsoft.com/pt-br/ef/core/modeling/relationships/one-to-many?ref=azurebrasil.cloud)*:*

`````
namespace EfCoreViews.Models;

public class Author
{
    public Guid Id { get; set; }
    public string Name { get; set; } = default!;
    public IList<Book> Books { get; set; } = new List<Book>();
}
```

`````
namespace EfCoreViews.Models;

public class Book
{
    public Guid Id { get; set; }
    public string Name { get; set; } = default!;
    public Guid AuthorId { get; set; } = default!;
    public Author Author { get; set; } = default!;
}
```

Com as entidades prontas, podemos criar suas [configurações](https://learn.microsoft.com/en-us/ef/core/modeling/?ref=azurebrasil.cloud) para o [*code-first*](https://learn.microsoft.com/pt-br/ef/core/?ref=azurebrasil.cloud)*:*

`````
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace EfCoreViews.Models.Configurations;

public class AuthorConfiguration :  IEntityTypeConfiguration<Author>
{
    public void Configure(EntityTypeBuilder<Author> builder)
    {
        builder.HasKey(e => e.Id);
        
        builder.Property(e => e.Name)
            .IsRequired();

        builder.HasData(new List<Author>
        {
            new()
            {
                Id = Guid.Parse("92338F02-F3A5-4C82-AC9F-F9DC1A8D7256"),
                Name = "J. R. R. Tolkien"
            },
            new()
            {
                Id = Guid.Parse("D7890984-FC4E-4AFA-8FC4-530F4C684A26"),
                Name = "James Carroll"
            }
        });
    }
}
```

``````
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace EfCoreViews.Models.Configurations;

public class BookConfiguration :  IEntityTypeConfiguration<Book>
{
    public void Configure(EntityTypeBuilder<Book> builder)
    {
        builder.HasKey(e => e.Id);
        
        builder.Property(e => e.Name)
            .IsRequired();

        builder.HasOne(x => x.Author)
            .WithMany(x => x.Books)
            .HasForeignKey(x => x.AuthorId);
        
        builder.HasData(new List<Book>
        {
            new()
            {
                Id = Guid.Parse("2AE6873C-31BC-48DE-85F9-C63289A312B3"),
                AuthorId = Guid.Parse("92338F02-F3A5-4C82-AC9F-F9DC1A8D7256"),
                Name = "The lord of the rings"
            },
            new()
            {
                Id = Guid.Parse("72C6EC9B-3964-4272-BED5-4D460020B79B"),
                AuthorId = Guid.Parse("92338F02-F3A5-4C82-AC9F-F9DC1A8D7256"),
                Name = "The hobbit"
            }
        });
    }
}
```

Apenas um detalhe. Fizemos o [*seed*](https://learn.microsoft.com/en-us/ef/core/modeling/data-seeding?ref=azurebrasil.cloud) de alguns dados!

Para finalizar as configurações do EF Core, precisamos criar a classe principal dessa ferramenta, o *AppDbContext* que herda de [*DbContext*](https://learn.microsoft.com/en-us/ef/core/dbcontext-configuration/?ref=azurebrasil.cloud):

``````
using EfCoreViews.Models;
using Microsoft.EntityFrameworkCore;

namespace EfCoreViews;

public class AppDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseSqlServer(@"Server=localhost;Database=MyDb;User Id=Sa;Password=Teste12345!;TrustServerCertificate=true");
    }
    
     public DbSet<Book> Books { get; set; } = null!;
     public DbSet<Author> Authors { get; set; } = null!;
    

     protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly);
    }
}
```

*Vamos criar a migration* e aplicá-la ao banco de dados.

``````
dotnet ef migrations add InitialCreate
dotnet ef database update 
```

Com os comandos finalizados, podemos ver que as tabelas foram criadas!

Obs: Estou utilizando o [Azure Data Studio](https://azure.microsoft.com/pt-br/products/data-studio?ref=azurebrasil.cloud)!

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2024/04/Screen-Shot-2024-04-29-at-22.46.58.png)

Na classe Program.cs, podemos criar um pequeno código para fazer uma *query* que utiliza algumas manipulações extras de dados ([*Include*](https://learn.microsoft.com/en-us/ef/core/querying/related-data/eager?ref=azurebrasil.cloud) e *Select*).

````
// See https://aka.ms/new-console-template for more information

using EfCoreViews;
using Microsoft.EntityFrameworkCore;

await using var context = new AppDbContext();

var results = await context.Authors
    .Include(x => x.Books)
    .Select(x => new
    {
        Author = x,
        BookCount = x.Books.Count
    })
    .ToListAsync();

foreach (var result in results)
{
    Console.WriteLine($"Author: {result.Author.Name} -> Book count: {result.BookCount}");
}
```

Temos o resultado:

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2024/04/Screen-Shot-2024-04-29-at-22.57.51.png)

A ideia agora é criar uma *view* que realiza essa mesma *query.* Para que essa *view* seja versionada juntamente com o código-fonte, vamos criar uma *migration* vazia por meio do seguinte comando:

```
 dotnet ef migrations add AddView
 
```

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2024/05/Screen-Shot-2024-05-09-at-18.08.03.png)

Vamos aprimorar seu conteúdo com o seguinte texto:

````
using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace EfCoreViews.Migrations
{
    /// <inheritdoc />
    public partial class AddView : Migration
    {
        /// <inheritdoc />
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.Sql(@"
            CREATE VIEW 
                AuthorBookCounting
            AS
            SELECT 
                a.Name AS Author,
                COUNT(b.Id) AS BookCount
            FROM 
                Authors a
            LEFT JOIN
                Books b ON b.AuthorId = a.Id
            GROUP BY 
                a.Name;
                ");
        }

        /// <inheritdoc />
        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.Sql("DROP VIEW AuthorBookCounting");
        }
    }
}

```

Observe que no método [*Up*](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.migrations.migration.up?view=efcore-8.0&ref=azurebrasil.cloud)*,* criamos a view. E no método [Down](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.migrations.migration.down?view=efcore-8.0&ref=azurebrasil.cloud), a deletamos.

Para servir como retorno da *view*, vamos criar um modelo chamado *AuthorBookCount.*

`````
namespace EfCoreViews.Models;

public class AuthorBookCount
{
    public Guid Id { get; set; }
    public string Author { get; set; } = default!;
    public int BookCount { get; set; } = default!;
}
```

el

Precisamos ainda acionar um novo [*DbSet*](https://learn.microsoft.com/pt-br/dotnet/api/microsoft.entityframeworkcore.dbset-1?view=efcore-8.0&ref=azurebrasil.cloud) ao *AppDbContex,* e a [configuração](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.relationalquerytypebuilderextensions.toview?view=efcore-2.2&ref=azurebrasil.cloud) (*code-first*) do modelo *AuthorBookCount.*

````
public DbSet<AuthorBookCount> AuthorBookCount { get; set; } = null!;
```

`````
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace EfCoreViews.Models.Configurations;

public class AuthorBookCountConfigurationConfiguration :  IEntityTypeConfiguration<AuthorBookCount>
{
    public void Configure(EntityTypeBuilder<AuthorBookCount> builder)
    {
        builder.HasKey(e => e.Id);
        builder.ToView("AuthorBookCounting");
    }
}
```

Com essas modificações prontas, vamos modificar o código do Program.cs:

`````
using EfCoreViews;
using Microsoft.EntityFrameworkCore;

await using var context = new AppDbContext();

var results = await context.AuthorBookCount.ToListAsync();

foreach (var result in results)
{
    Console.WriteLine($"Author: {result.Author} -> Book count: {result.BookCount}");
}

```

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2024/05/Screen-Shot-2024-05-09-at-20.55.47.png)

Observe que realizamos a *query* por meio da *view* AuthorBookCount*!*

Você já pode baixar o projeto por esse [link](https://github.com/TallesValiatti/EfCoreViews/tree/main/Migrations?ref=azurebrasil.cloud), e não esquece de me seguir no [LinkedIn](https://www.linkedin.com/in/tallesvaliatti/?ref=azurebrasil.cloud)!

Até a próxima, abraços!