.NET

11 out, 2017

ASP .NET Core – Iniciando com ASP .NET Core MVC e Entity Framework Core no VS 2017 – Parte 03

Publicidade

Neste artigo vamos iniciar a criação de controllers e views em uma aplicação ASP .NET Core MVC usando o Entity Framework Core no Visual Studio 2017.

Continuando a segunda parte do artigo, vamos definir um controlador MVC em nosso projeto e as respectivas Views que usarão o EF para consultar e persistir dados.

Criando um Controller e Views

Se você não sabe o que é um Controller então pode ler os seguintes artigos:

Os Controllers ou Controladores são os componentes que lidam com a interação do usuário, trabalham com o modelo e, finalmente, selecionam uma exibição de renderização que mostra essa interface ao usuário. Por padrão, os controladores são colocados na pasta Controllers da solução.

A criação automática dos métodos Actions para realizar o CRUD e as Views é conhecida como Scaffolding. O Scaffolding irá criar automaticamente os métodos Action e as Views, e, quando você precisar personalizar o código gerado, você pode usar classes parciais ou você regenera o código quando houver alterações.

Vamos iniciar criando um controlador em nosso projeto. Clique com o botão direito do mouse sobre a pasta Controllers, e a seguir clique em Add -> Controller;

Na janela Add MVC Dependencies, selecione a opção Minimal Dependencies e clique no botão Add:

O VS 2017 vai adicionar as dependências necessárias para montar o controller.

Após isso, repita o procedimento e clique com o botão direito do mouse sobre a pasta Controllers, e a seguir clique em Add -> Controller;

Na janela Add Scaffold selecione a opção: MVC Controller with views, using Entity Framework:

Clique no botão Add.

Agora na janela Add Controller vamos fazer as seguintes definições:

Model Class: Selecione Estudante(UniversidadeMacoratti.Models)

Data context class: clique no botão + e selecione EscolaContexto(UniversidadeMacoratti.Data) e em seguida, clique no botão Add;

Ao clicar no botão Add, o mecanismo de Scaffolding do Visual Studio irá criar um arquivo EstudantesController.cs na pasta Controllers, e um conjunto de Views (arquivos .cshtml), na pasta /Views/Estudantes, que funcionam com o controlador.

A figura abaixo mostra o resultado:

Note que o controlador toma o nosso contexto, EscolaContexto, como um parâmetro de construtor.

A injeção de dependência do contâiner ASP .NET Core vai cuidar de passar uma instância de EscolaContexto para o controlador, porque isso foi configurado no arquivo Startup.cs, lembra?

O controlador contém um método Action Index que exibe todos os estudantes existentes no banco de dados, ele obtém uma lista de estudantes do conjunto de entidades Estudantes lendo a propriedade Estudantes da instância do contexto do banco de dados.

 // GET: Estudantes
        public async Task<IActionResult> Index()
        {
            return View(await _context.Estudantes.ToListAsync());
        }

Note que é retornado uma View, a view Index.cshtml, que exibe uma lista de estudantes em uma tabela: (Eu já traduzi os textos)

@model IEnumerable<UniversidadeMacoratti.Models.Estudante>
@{
    ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
    <a asp-action="Create">Criar Novo</a>
</p>
<table class="table">
    <thead>
        <tr>
                <th>
                    @Html.DisplayNameFor(model => model.SobreNome)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Nome)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.DataMatricula)
                </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.SobreNome)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Nome)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.DataMatricula)
            </td>
            <td>
                <a asp-action="Edit" asp-route-id="@item.EstudanteID">Editar</a> |
                <a asp-action="Details" asp-route-id="@item.EstudanteID">Detalhes</a> |
                <a asp-action="Delete" asp-route-id="@item.EstudanteID">Deletar</a>
            </td>
        </tr>
         }
    </tbody>
</table>

Pressione F5 ou CTRL + F5 para executar o projeto e a seguir clique na guia Estudantes para ver os dados de teste que definimos no método DbInitializer.Initialize.

Dependendo do tamanho da janela do seu navegador, você verá o link da guia Estudante na parte superior da página ou você terá que clicar no ícone de navegação no canto superior direito para ver o link.

Vamos agora dar uma espiada no banco de dados e nas tabelas.

Espiando o banco de dados e as tabelas

Quando você iniciar a aplicação, o método DbInitializer.Initialize chama o método EnsureCreated e o EF percebe que não existe um banco de dados, então ele cria um, e a seguir, as tabelas são preenchidas com os dados de testes, definido no código do método Initialize.

Vamos verificar o banco de dados e as tabelas criados usando o SQL Server Object Explorer (SSOX). Feche o navegador e pare a aplicação.

No menu View, clique em SQL Server Object Explorer;

A seguir clique no item (localdb)\MSSQLLocalDB(SQL Server 13.0.1601)

Depois, clique no banco de dados UniversidadeMacoratti1 e expanda o nó Table para visualizar as tabelas do banco de dados:

Clique com o botão direito do mouse sobre a tabela Estudante e a seguir em View Data para visualizar as colunas que foram criadas e as linhas que foram inseridas na tabela:

O banco de dados .mdf e o arquivo .ldf estão presentes na pasta c:\Users\user

Podemos alterar a estrutura da classe Estudante , incluindo uma nova coluna Email, por exemplo, e, ao executar novamente a aplicação, o método EnsureCreated executado no início, irá recriar toda a estrutura dos dados agora incluindo a nova coluna.

Convenções usadas pelo EF

A quantidade de código que você teve que escrever para que o Entity Framework pudesse criar um banco de dados completo para você, foi mínima por causa do uso de convenções que o Entity Framework faz. O Entity Framework, por padrão, adota algumas convenções (Conventions) que ele usa para realizar algumas operações.

Mas o que vem a ser essas convenções?

Em nosso contexto, podemos dizer que uma convenção é uma regra padrão pelo qual não teremos que fazer algumas configurações de mapeamento para nossas entidades, sendo que o EF vai , baseado nessas convenções, realizar as tarefas de forma automática.

Vejamos algumas delas:

  • Os nomes das propriedades DbSet são usadas ​​para dar nomes às tabelas. Para entidades não referenciadas por uma propriedade DbSet, nomes de classe de entidade são usados ​​como nomes de tabelas;
  • Os nomes das propriedades da entidade são usados ​​para dar nomes às colunas;
  • As propriedades de entidade que são nomeadas como ID ou classnameID são reconhecidas como propriedades de chave primária;
  • O comportamento convencional pode ser substituído. Por exemplo, você pode especificar explicitamente nomes de tabela, e, você pode definir nomes de colunas e definir qualquer propriedade como chave primária ou chave estrangeira, como veremos mais adiante.

Código Assíncrono

Se você espiou o código gerado na criação do controlador EstudantesController, notou que foi gerado código assíncrono. A programação assíncrona é o padrão na ASP .NET Core e no EF Core.

Um servidor web tem um número limitado de threads disponíveis, e em situações de alta carga, todas as threads disponíveis podem estar em uso. Quando isso acontece, o servidor não pode processar novas solicitações até que as threads sejam liberadas.

Ao usar um código síncrono, muitas threads podem ficar bloqueadas enquanto não estão realmente fazendo qualquer trabalho porque estão esperando uma tarefa ser concluída.

Com o código assíncrono, quando um processo está aguardando a conclusão, sua thread é liberada para o servidor usar e processar outras solicitações. Como resultado, o código assíncrono permite que os recursos do servidor sejam usados ​​com mais eficiência e o servidor está habilitado para processar mais tráfego sem atrasos.

O código assíncrono introduz uma pequena quantidade de sobrecarga em tempo de execução, mas para situações de baixo tráfego, o desempenho atingido é desprezível, enquanto que para situações de alto tráfego, a melhoria do desempenho potencial é substancial.

No código a seguir, a palavra-chave async, Task<T>, a palavra-chave await e o método ToListAsync fazem o código executar de forma assíncrona.

public async Task<IActionResult> Index()
{
return View(await _context.Students.ToListAsync());
}

  • async diz ao compilador para gerar callbacks para partes do método e para criar automaticamente o objeto Task<IActionResult> que é retornado;
  • O tipo de retorno Task<IActionResult> representa o trabalho em andamento com o resultado do tipo IActionResult;
  • await faz com que o compilador divida o método em partes. A primeira parte termina com a operação que é iniciada assincronamente e a segunda parte é posta no método callback quando a operação termina;
  • ToListAsync é a versão assíncrona do método de extensão ToList;

Ao escrever código assíncrono na utilização do Entity Framework, fique atento ao seguinte:

– Somente as instruções que fazem com que consultas ou comandos sejam enviados para o banco de dados são executados de forma assíncrona. Isso inclui, por exemplo, ToListAsync, SingleOrDefaultAsync e SaveChangesAsync. Isso não inclui instruções que apenas alteram um IQueryable, como por exemplo: var estudantes = context.Estudantes.Where (s => s.SobreNome == “Macoratti”).

– Um contexto EF não é thread-safe: não tente fazer várias operações em paralelo. Quando você chama qualquer método EF assíncrono, use sempre a palavra-chave await.

– Se você quiser tirar proveito dos benefícios de desempenho do código assíncrono, certifique-se de que todos os pacotes de biblioteca que você está usando, também usam async, se chamarem qualquer método Entity Framework que faça com que as consultas sejam enviadas para a base de dados.

Na próxima parte do artigo vamos continuar criando os métodos para realizar as operações CRUD.