ASP .NET Core - Iniciando com ASP .NET Core MVC e EF Core - II

 Neste artigo eu vamos iniciar a criação de uma aplicação ASP .NET Core MVC usando o Entity Framework Core no Visual Studio.

Continuando a primeira parte do artigo vamos definir o contexto do nosso banco de dados e inicializar as tabelas com dados de testes.

Criando a classe de contexto do Banco de dados

O Entity Framework permite consultar, inserir, atualizar e excluir dados, usando objetos CLR(Common Language Runtime) conhecidos como entidades; ele mapeia as entidades e relacionamentos que são definidos no seu modelo de entidades para um banco de dados e fornece facilidades para realizar as seguintes tarefas:

1- Materializar dados retornados do banco de dados como objetos de entidade;
2- Controlar as alterações que foram feitas nos objetos;
3- Lidar com concorrência;
4- Propagar as alterações feitas nos objetos de volta ao banco de dados;
5- Vincular objetos a controles.


A principal classe responsável pela interação com os objetos de dados é a classe System.Data.Entity.DbContext (muitas vezes referida como o contexto).

Essa classe de contexto administra os objetos entidades durante o tempo de execução, o que inclui preencher objetos com dados de um banco de dados, controlar alterações, e persistir dados para o banco de dados.

A maneira recomendada para trabalhar com o contexto é definir uma classe que deriva de DbContext e expõe as propriedades de DbSet que representam as coleções das entidades especificadas no contexto.

Essa classe é chamada de classe de contexto do banco de dados e coordena a funcionalidade do Entity Framework para um dado modelo de dados. No código dessa classe você especifica quais entidades estão incluídas no modelo de dados. Você também pode personalizar determinado comportamento do Entity Framework. Neste projeto, a nossa classe de contexto será chamada EscolaContexto.

Vamos criar uma pasta chamada Data, via menu Project-> New Folder, e a seguir incluir nesta pasta o arquivo EscolaContexto.cs incluindo na classe o seguinte código:

using Microsoft.EntityFrameworkCore;
using UniversidadeMacoratti.Models;

namespace UniversidadeMacoratti.Data
{
    public class EscolaContexto : DbContext
    {
        public EscolaContexto(DbContextOptions<EscolaContexto> options) : base(options)
        {            
        }

        public DbSet<Curso> Cursos { get; set; }
        public DbSet<Matricula> Matriculas { get; set; }
        public DbSet<Estudante> Estudantes { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Curso>().ToTable("Curso");
            modelBuilder.Entity<Matricula>().ToTable("Matricula");
            modelBuilder.Entity<Estudante>().ToTable("Estudante");

        }
    }
}

Este código cria uma propriedade DbSet para cada conjunto de entidades. Na terminologia Entity Framework, um conjunto de entidades corresponde a uma tabela de banco de dados e uma entidade corresponde a uma linha na tabela.

Você poderia ter omitido as instruções DbSet<Matricula> e DbSet<Curso> e funcionaria da mesma forma. O Entity Framework os incluiria implicitamente porque a entidade Estudante faz referência à entidade Matricula e a entidade Matricula faz referência a entidade Curso.

Quando o banco de dados é criado, o EF cria tabelas que têm nomes iguais aos nomes definidos na propriedade DbSet. Os nomes das propriedades para coleções em geral estão no plural (Estudantes, Matriculas, Cursos) .

Neste exemplo vamos alterar esse comportamento padrão, especificando os nomes de tabelas em singular no DbContext. Para fazer isso sobrescrevemos o método OnModelCreating() e definimos explicitamente o código que determina que o nome das tabelas geradas serão : Curso, Matricula e Estudante.

Registrando o contexto com injeção de dependência

A ASP.NET Core implementa a injeção de dependência por padrão. Os serviços (como o contexto de banco de dados do EF) são registrados com injeção de dependência durante a inicialização do aplicativo. Componentes que requerem esses serviços (como controladores MVC) fornecem esses serviços através de parâmetros do construtor. Mais adiante iremos definir no construtor do controlador a instância do contexto.

Para registrar o nosso contexto EscolaContexto como um serviço, abra o arquivo Startup.cs e adicione as linhas realçadas ao método ConfigureServices:

using Microsoft.EntityFrameworkCore;
...
....

      // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddDbContext<EscolaContexto>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
            // Add framework services.
            services.AddMvc();
        }
....

O nome da string de conexão é passada para o contexto pela chamada do método no objeto DbContextOptionsBuilder. Para o desenvolvimento local a ASP .NET Core obtém a string de conexão do arquivo appsettings.json.

Vamos então abrir o arquivo appsettings.json e adicionar a string de conexão conforme mostrado a seguir:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=UniversidadeMacoratti1;Trusted_Connection=True;MultipleActiveResultSets=true"
  },

  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Warning"
    }
  }
}

A string de conexão especifica um banco de dados SQL Server LocalDB. O LocalDB é uma versão leve do mecanismo de Banco de Dados do SQL Server Express e destina-se ao ambiente de desenvolvimento não sendo recomendado para o ambiente de produção.

O LocalDB é iniciado sob demanda e é executado no modo user, pelo que não existe uma configuração complexa. Por padrão, o LocalDB cria os arquivos de banco de dados .mdf no diretório C:/Users/<user>.

Inicializando o banco de dados com dados para testes

O Entity Framework criará um banco de dados vazio para você. Vamos então definir o código para poder inicializar as tabelas do banco de dados com alguns dados para realizar testes em nossa aplicação.

Vamos usar o método EnsureCreated para criar automaticamente o banco de dados. (Para fazer alterações no modelo mais adiante vamos usar o Code First Migrations para alterar o esquema do banco de dados excluir e recriar o banco de dados novamente.)

Na pasta Data, crie um novo arquivo chamado DbInitializer.cs e inclua o código a seguir que faz com que o banco de dados seja criado quando necessário e carregue dados de teste nas tabelas do banco:

using System;
using System.Linq;
using UniversidadeMacoratti.Models;

namespace UniversidadeMacoratti.Data
{
    public class DbInitializer
    {
        public static void Initialize(EscolaContexto context)
        {
            context.Database.EnsureCreated();

            // procura por qualquer estudante
            if (context.Estudantes.Any())
            {
                return;  //O banco foi inicializado
            }

            var estudantes = new Estudante[]
            {
            new Estudante{Nome="Carlos",SobreNome="Silveira",DataMatricula=DateTime.Parse("2015-09-01")},
            new Estudante{Nome="Maria",SobreNome="Alonso",DataMatricula=DateTime.Parse("2012-09-01")},
            new Estudante{Nome="Bianca",SobreNome="Almeida",DataMatricula=DateTime.Parse("2013-09-01")},
        new Estudante{Nome="Jose Carlos",SobreNome="Siqueira",DataMatricula=DateTime.Parse("2012-09-01")},
            new Estudante{Nome="Yuri",SobreNome="Silva",DataMatricula=DateTime.Parse("2012-09-01")},
            new Estudante{Nome="Mario",SobreNome="Domingues",DataMatricula=DateTime.Parse("2011-09-01")},
            new Estudante{Nome="Laura",SobreNome="Santos",DataMatricula=DateTime.Parse("2013-09-01")},
            new Estudante{Nome="Jefferson",SobreNome="Bueno",DataMatricula=DateTime.Parse("2015-09-01")}

            };
            foreach (Estudante s in estudantes)
            {
                context.Estudantes.Add(s);
            }
            context.SaveChanges();

            var cursos = new Curso[]
            {
            new Curso{CursoID=1050,Titulo="Quimica",Creditos=3,},
            new Curso{CursoID=4022,Titulo="Economia",Creditos=3,},
            new Curso{CursoID=4041,Titulo="Economia",Creditos=3,},
            new Curso{CursoID=1045,Titulo="Cálculo",Creditos=4,},
            new Curso{CursoID=3141,Titulo="Trigonometria",Creditos=4,},
            new Curso{CursoID=2021,Titulo="Música",Creditos=3,},
            new Curso{CursoID=2042,Titulo="Literatura",Creditos=4,}

            };
            foreach (Curso c in cursos)
            {
                context.Cursos.Add(c);
            }
            context.SaveChanges();

            var matriculas = new Matricula[]
            {
            new Matricula{EstudanteID=1,CursoID=1050,Nota=Nota.A},
            new Matricula{EstudanteID=1,CursoID=4022,Nota=Nota.C},
            new Matricula{EstudanteID=1,CursoID=4041,Nota=Nota.B},
            new Matricula{EstudanteID=2,CursoID=1045,Nota=Nota.B},
            new Matricula{EstudanteID=2,CursoID=3141,Nota=Nota.F},
            new Matricula{EstudanteID=2,CursoID=2021,Nota=Nota.F},
            new Matricula{EstudanteID=3,CursoID=1050},
            new Matricula{EstudanteID=4,CursoID=1050,},
            new Matricula{EstudanteID=4,CursoID=4022,Nota=Nota.F},
            new Matricula{EstudanteID=5,CursoID=4041,Nota=Nota.C},
            new Matricula{EstudanteID=6,CursoID=1045},
            new Matricula{EstudanteID=7,CursoID=3141,Nota=Nota.A},

            };
            foreach (Matricula e in matriculas)
            {
                context.Matriculas.Add(e);
            }
            context.SaveChanges();
        }
    }
}

O código acima verifica se existe alguma informação sobre estudantes no banco de dados; se não existir, ele assume que temos um banco de dados novo e então ele alimenta as tabelas com os dados.

Agora precisamos modificar o método Configure do arquivo Startup.cs para chamar este método que vai alimentar as tabelas quando a aplicação iniciar.

Abra o arquivo Startup.cs e inclua o nosso contexto EscolaContexto na assinatura do método de forma que a injeção de dependência da ASP .NET Core pode fornecer o recurso para a classe DbInitializer:

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, EscolaContexto context)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}" );
            });

            DbInitializer.Initialize(context);
        }

Agora na primeira vez que você executar a aplicação, o banco de dados será criado e alimentado com os dados para testes.

Sempre que você alterar seu modelo de dados, você pode excluir o banco de dados, atualizar seu método para alimentar dados e começar de novo com um novo banco de dados da mesma maneira.

Com isso concluímos a criação das nossas entidades e preparamos nosso banco de dados com alguns dados de testes.

Na próxima parte do artigo vamos continuar criando controladores e views para gerenciar as informações.

Porque todos quantos fostes batizados em Cristo já vos revestistes de Cristo.
Nisto não há judeu nem grego; não há servo nem livre; não há macho nem fêmea; porque todos vós sois um em Cristo Jesus.
Gálatas 3:27-28

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?


Referências:


José Carlos Macoratti