.NET

31 ago, 2017

ASP .NET Core – iniciando com ASP .NET Core MVC e Entity Framework Core no VS 2017 – Parte 01

Publicidade

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

Esta série de artigos inicia a criação de uma aplicação ASP .NET Core MVC usando o Entity Framework Core com o Visual Studio 2017, e, esta baseada nos artigos originais publicados em https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro com algumas adaptações, traduções e ajustes.

A aplicação de exemplo criada será o site de uma Universidade fictícia que eu vou chamar de Universidade Macoratti e vai incluir funcionalidades como admissão de alunos, criação de cursos e atribuições de instrutores onde iremos usar a ASP .NET Core 1.1 MVC, o Entity Framework Core 1.1 e o Visual Studio 2017.

Você pode baixar a aplicação original neste link : https://github.com/aspnet/Docs/tree/master/aspnetcore/data/ef-mvc/intro/samples/cu-final

Lembrando que o Entity Framework Core 1.1 é a última versão do EF mas ele não possui todos os recursos do Entity Framework 6.x. (Ele esta disponível via nuget: Install-Package Microsoft.EntityFrameworkCore)

O Entity Framework Core (EF Core) é uma versão leve, extensível e multiplataforma do Entity Framework. O EF Core introduz muitas melhorias e novos recursos quando comparado com o EF6.x. O EF Core mantém a experiência do desenvolvedor do EF6.x e a maioria das APIs de alto nível permanecem as mesmas, então o EF Core vai te parecer muito familiar se você conhece o Entity Framework 6.x.

Ao mesmo tempo, o EF Core é construído sobre um conjunto completamente novo de componentes principais. Isso significa que o EF Core não herda automaticamente todos os recursos do EF6.x. Alguns desses recursos serão exibidos em lançamentos futuros (como o lazy loading e a resiliência de conexão), outros recursos menos usados não serão implementados no EF Core. O núcleo novo, extensível e leve também nos permitiu adicionar alguns recursos ao EF Core que não serão implementados no EF6.x.

Para acompanhar este artigo você precisa ter instalado o Visual Studio Community 2017 com os seguintes workloads (cargas de trabalho) instalados:

/wp-admin/async-upload.php Failed to load resource:

Criando o projeto Exemplo : Universidade Macoratti no VS Community 2017

A aplicação exemplo que vamos construir nestes tutoriais é um simples site de uma universidade onde os usuários podem visualizar e atualizar informações de alunos, cursos e instrutores, onde iremos focar na utilização do Entity Framework Core.

Vamos iniciar criando uma aplicação ASP .NET Core MVC Web Application.

Abra no VS community 2017 e no menu File clique em New Project;

A seguir selecione o template Visual C# -> .NET Core e marque ASP .NET Core Web Application (.NET Core);

/wp-admin/async-upload.php Failed to load resource:

Dessa forma estamos criando uma aplicação web (MVC com views e controllers) usando o framework .NET Core.

Informe o nome UniversidadeMacoratti (ou outro a seu gosto) e clique no botão OK;

Na próxima janela escolha a versão ASP .NET Core 1.1 e marque o template Web Application sem autenticação e clique no botão OK;

/wp-admin/async-upload.php Failed to load resource:

Você terá o seguinte projeto criado:

/wp-admin/async-upload.php Failed to load resource:

O Visual Studio utiliza um template padrão para o projeto Web Application que é criado e pode ser visto na figura acima.

Temos assim uma aplicação funcional, na verdade , um simples projeto inicial, que será o nosso ponto de partida.

Pressione F5 para rodar a aplicação no modo debug ou Ctrl+F5 para rodar no modo não debug. (O VS inicia o servidor IIS Express e executa a nossa aplicação.)

/wp-admin/async-upload.php Failed to load resource:

Observe que o endereço na barra de navegação exibe localhost:14240/ que indica a porta onde a aplicação esta atendendo.

Ajustando o estilo do site

Vamos fazer alguns ajustes iniciais apenas para alterar o menu do site, o seu leiaute e a página incial.

Para isso vamos abrir o arquivo _Layout.cshtml na pasta /Views/Shared e realizar as seguintes alterações:

  • Traduzir os textos para o português quando pertinente;
  • Alterar o texto UniversidadeMacoratti para Universidade Macoratti;
  • Incluir entradas de menu para as seguintes opções : Estudantes, Cursos, Instrutores e Departamentos;
  • Deletar a opção Contato do menu;

Abaixo temos as alterações implementadas no arquivo _Layout.cshtml:

@inject Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet JavaScriptSnippet
<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8" />
 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 <title>@ViewData["Title"] - Universidade Macoratti</title>
 <environment names="Development">
 <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
 <link rel="stylesheet" href="~/css/site.css" />
 </environment>
 <environment names="Staging,Production">
 <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
 asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
 asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
 <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
 </environment>
 @Html.Raw(JavaScriptSnippet.FullScript)
</head>
<body>
 <nav class="navbar navbar-inverse navbar-fixed-top">
 <div class="container">
 <div class="navbar-header">
 <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
 <span class="sr-only">Toggle navigation</span>
 <span class="icon-bar"></span>
 <span class="icon-bar"></span>
 <span class="icon-bar"></span>
 </button>
 <a asp-area="" asp-controller="Home" asp-action="Index" class="navbar-brand">Universidade Macoratti</a>
 </div>
 <div class="navbar-collapse collapse">
 <ul class="nav navbar-nav">
 <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
 <li><a asp-area="" asp-controller="Home" asp-action="About">Sobre</a></li>
 <li><a asp-area="" asp-controller="Estudantes" asp-action="Index">Estudantes</a></li>
 <li><a asp-area="" asp-controller="Cursos" asp-action="Index">Cursos</a></li>
 <li><a asp-area="" asp-controller="Instrutores" asp-action="Index">Instrutores</a></li>
 <li><a asp-area="" asp-controller="Departamentos" asp-action="Index">Departamentos</a></li>
 </ul>
 </div>
 </div>
 </nav>
 <div class="container body-content">
 @RenderBody()
 <hr />
 <footer>
 <p>&copy; 2017 - Universidade Macoratti</p>
 </footer>
 </div>
 <environment names="Development">
 <script src="~/lib/jquery/dist/jquery.js"></script>
 <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
 <script src="~/js/site.js" asp-append-version="true"></script>
 </environment>
 <environment names="Staging,Production">
 <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
 asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
 asp-fallback-test="window.jQuery"
 crossorigin="anonymous"
 integrity="sha384-K+ctZQ+LL8q6tP7I94W+qzQsfRV2a+AfHIi9k8z8l9ggpc8X+Ytst4yBo/hH+8Fk">
 </script>
 <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
 asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
 asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
 crossorigin="anonymous"
 integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
 </script>
 <script src="~/js/site.min.js" asp-append-version="true"></script>
 </environment>
 @RenderSection("Scripts", required: false)
</body>
</html>

A seguir vamos alterar o código da view Index.cshtml na pasta /Views/Home substituindo o texto existente pelo texto exibido a seguir:

@{
 ViewData["Title"] = "Home Page";
}
<div class="jumbotron">
 <h1>Universidade Macoratti</h1>
</div>
<div class="row">
 <div class="col-md-4">
 <h2>Bem-Vindo à Universidade Macoratti</h2>
 <p>
 Universidade Macoratti é uma aplicação exemplo que
 demonstra como usar o Entity Framework Core em uma
 aplicação ASP.NET Core MVC web application.
 </p>
 </div>
 <div class="col-md-4">
 <h2>Construindo deste o início</h2>
 <p>Você pode criar a aplicação seguindo os seguintes passos nesta série de tutoriais.</p>
 <p><a class="btn btn-default" href="https://docs.asp.net/en/latest/data/ef-mvc/intro.html">Veja o tutorial &raquo;</a></p>
 </div>
 <div class="col-md-4">
 <h2>Baixe o projeto completo</h2>
 <p>Você pode baixar o projeto completo do GitHub.</p>
 <p><a class="btn btn-default" href="https://github.com/aspnet/Docs/tree/master/aspnet/data/ef-mvc/intro/samples/cu-final">Veja o código fonte do projeto &raquo;</a></p>
 </div>
</div>

Após fazer essas alterações executando novamente a aplicação (F5 ou CTRL+F5) teremos o seguinte resultado:

/wp-admin/async-upload.php Failed to load resource:

Simplificamos assim o leiaute da aplicação. Vamos agora incluir o suporte ao Entity Framework Core em nossa aplicação.

Adicionando o suporte para o Entity Framework Core via Nuget

Vamos adicionar o suporte ao EF Core em nosso projeto e instalar o provedor do banco de dados que vamos usar. No exemplo deste artigo vamos instalar o provedor SQL Server : Microsoft.EntityFrameworkCore.SqlServer.

Para instalar esse pacote abra uma janela do Package Manager Console via menu Tools e digite o comando : Install-Package Microsoft.EntityFrameworkCore.SqlServer

/wp-admin/async-upload.php Failed to load resource:

Este pacote e suas dependências (Microsoft.EntityFrameworkCore e Microsoft.EntityFrameworkCore.Relational) fornece o suporte em tempo de execução ao EF.(Mais adiante iremos instalar outro pacote para a migração)

Nota: O EF para no .NET Core não possui todas as funcionalidades do EF 6. (lazy loading não esta suportado ainda)

Criando o nosso modelo de dados

Agora que temos o suporte ao EF Core vamos criar as classes das entidades para a nossa aplicação. Vamos inciar com as seguintes três entidades :

/wp-admin/async-upload.php Failed to load resource:

Neste modelo temos que :

  • Existe um relacionamento um-para-muitos entre as entidades Estudante e Matricula
  • Existe um relacionamento um-para-muitos entre as entidades Curso e Matricula

/wp-admin/async-upload.php Failed to load resource:

Dessa forma um estudante pode estar matriculado em qualquer número de cursos e um curso pode ter qualquer número de estudantes matriculados.

Vamos agora criar classes que representam as nossas entidades.

1- Criando a entidade Estudante

Vamos criar uma pasta chamada “Models” no projeto para nesta pasta definir o modelo de entidades.

Nota: Você pode colocar classes do modelo em qualquer lugar em seu projeto, mas a pasta Models é usada por convenção.

Na janela Solution Explorer, clique com o botão direito do mouse no projeto e selecione Add -> New Folder e informe o nome Models.

As classes são criadas na pasta Models clicando com o botão direito sobre a pasta, selecionando Add -> Class e a seguir informando o nome da classe.

Vamos iniciar criando o arquivo Estudante.cs e nele vamos definir a classe Estudante conforme abaixo:

using System;
using System.Collections.Generic;
namespace UniversidadeMacoratti.Models
{
 public class Estudante
 {
 public int EstudanteID { get; set; }
 public string SobreNome { get; set; }
 public string Nome { get; set; }
 public DateTime DataMatricula { get; set; }
 public ICollection<Matricula> Matriculas { get; set; }
 }
}

A propriedade EstudanteID será a coluna de chave primária da tabela de banco de dados que corresponde a essa classe. Por padrão, o Entity Framework interpreta uma propriedade que é chamada de ID ou nome_classeID como sendo a chave primária.(Podemos alterar esse comportamento com annotations)

A propriedade de Matricula é uma propriedade de navegação. As propriedades de navegação tratam outras entidades que estão relacionadas com esta entidade permitindo que acessemos propriedades relacionadas.

Neste caso, a propriedade Matriculas da entidade Estudante irá tratar todas as entidades Matricula que estão relacionadas com essa entidade Estudante. Ou seja , se um registro de estudante na base de dados possuir dois registros matricula relacionados, a propriedades de navegação Matriculas da entidade Estudante irá conter as duas entidades Matricula.

Se uma propriedade de navegação pode conter várias entidades (como nas relações many-to-many ou one-to-many), seu tipo deve ser uma lista na qual as entradas podem ser adicionadas, excluídas e atualizadas, como ICollection<T>. Você pode especificar ICollection<T> ou um tipo como uma List<T> ou HashSet<T>. Se você especificar ICollection<T>, o EF cria uma coleção HashSet<T> por padrão.

2- Criando a entidade Matricula

Na mesma pasta Models vamos criar a classe Matricula.cs e definir o código da classe Matricula conforme abaixo:

namespace UniversidadeMacoratti.Models
{
 public enum Nota
 {
 A, B, C, D, F
 }
 public class Matricula
 {
 public int MatriculaID { get; set; }
 public int CursoID { get; set; }
 public int EstudanteID { get; set; }
 public Nota? Nota { get; set; }
 public Curso Curso { get; set; }
 public Estudante Estudante { get; set; }
 }
}

A propriedade MatriculaID será a chave primária; Essa entidade usa o padrão classnameID em vez de ID por si mesmo como fizemos na entidade Estudante. É bom você escolher um padrão e usar esse padrão em todo o seu modelo de dados. Aqui, a variação ilustra que você pode usar qualquer padrão. Em um tutorial posterior, você verá como o uso de ID sem classname torna mais fácil implementar a herança no modelo de dados.

A propriedade Nota um enum. O ponto de interrogação após a declaração de tipo Nota indica que a propriedade Nota é anulável. Uma nota que é nula é diferente de uma nota zero – nula significa que uma nota não é conhecida ou ainda não foi atribuída.

A propriedade EstudanteID é uma chave estrangeira e a propriedade de navegação correspondente é Estudante. Uma entidade Matricula está associada a uma entidade Estudante, de modo que a propriedade só pode conter uma única entidade Estudante (ao contrário da propriedade de navegação Estudante.Matriculas que você viu anteriormente, que pode conter várias entidades Matricula.

A propriedade CursoID é uma chave estrangeira e a propriedade de navegação correspondente é Curso. Uma entidade Matricula está associada a uma entidade Curso.

O Entity Framework interpreta uma propriedade como uma propriedade de chave estrangeira se ela for nomeada assim : <nome da propriedade de navegação><nome da propriedade da chave primária> (Ex: EstudanteID para a propriedade de navegação do Estudante, uma vez que a chave primária da entidade Estudante é ID).

As propriedades de chave estrangeira também podem ser nomeadas simplesmente assim: <nome da propriedade da chave primária> (Ex: CursoID, uma vez que a chave principal da Curso é CursoID).

3- Criando a entidade Curso

Na mesma pasta Models vamos criar a classe Curso.cs e definir o código da classe Curso conforme abaixo:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
namespace UniversidadeMacoratti.Models
{
 public class Curso
 {
 [DatabaseGenerated(DatabaseGeneratedOption.None)]
 public int CursoID { get; set; }
 public string Titulo { get; set; }
 public int Creditos { get; set; }
 public ICollection<Matricula> Matriculas { get; set; }
 }
}

O atributo [DatabaseGenerated] é usado em campos computados e quando definido com a opção DatabaseGeneratedOption.None faz com que o banco de dados não gere um valor para a propriedade quando linhas forem inseridas ou atualizadas na respectiva tabela.

No caso ela esta sendo usada para que a propriedade CursoID não seja definida como um campo Identity pelo SQL Server.

Estamos usando a abordagem Code-First do Entity Framework e nesta abordagem escrevemos as nossas classes POCO em primeiro lugar e, em seguida, o EF cria o banco de dados a partir dessas classes POCO (Plain Old CLR Objects).

Dessa forma, quando decidimos usar o Code-First não precisamos começar nossa aplicação criando o banco de dados ou definindo um esquema mas podemos iniciar escrevendo classes .NET para definir o modelo de objetos do nosso domínio sem ter que misturar a lógica de persistência de dados com as classes.

Nota : O Entity Framework por padrão adota algumas convenções (Conventions) que ele usa para realizar algumas operações.

Dessa forma temos o nosso modelo de entidades pronto e vamos continuar a próxima parte do artigo criando o contexto do banco de dados e definindo os dados de testes que iremos usar.