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

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

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 MVC, o Entity Framework Core e o Visual Studio.

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:

Criando o projeto Exemplo :  Universidade Macoratti no VS Community 2017

A aplicação exemplo que vamos construir nesses 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);

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;

Você terá o seguinte projeto criado:

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.)

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:

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:

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

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 :

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

Relacionamento um-para-muitos :   um registro na Tabela A pode ter muitos registros coincidentes na Tabela B, mas um registro na Tabela B tem um só registro coincidente na Tabela A.  O relacionamento é representado pelo sinal: 1:N que expressa a cardinalidade do relacionamento.

Obs:Um relacionamento um-para-muitos é criado se apenas uma das colunas relacionadas é uma chave primária ou tem uma restrição de exclusividade.

A cardinalidade é um conceito importante para ajudar a definir o relacionamento, ela define o número de ocorrências em um relacionamento. Para determinar a cardinalidade, deve-se fazer a pergunta relativa ao relacionamento em ambas as direções. No exemplo a seguir, temos

Um Setor possui quantos empregados?  R: No mínimo 1 e no máximo N.
Um Empregado está alocado em quantos setores? R: No mínimo em 1 e no máximo em 1.

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.

O Senhor reinará eterna e perpetuamente; Êxodo 15:18

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