Criando um modelo de dados do Entity Framework para um aplicativo MVC ASP.NET (1 de 10)

por Tom Dykstra

Observação

Uma versão mais recente desta série de tutoriais está disponível, para Visual Studio 2013, Entity Framework 6 e MVC 5.

O aplicativo Web de exemplo da Contoso University demonstra como criar ASP.NET aplicativos MVC 4 usando o Entity Framework 5 e o Visual Studio 2012. O aplicativo de exemplo é um site de uma Contoso University fictícia. Ele inclui funcionalidades como admissão de alunos, criação de cursos e atribuições de instrutor. Esta série de tutoriais explica como criar o aplicativo de exemplo da Contoso University.

Code First

Há três maneiras de trabalhar com dados no Entity Framework: Database First, Model First e Code First. Este tutorial é para o Code First. Para obter informações sobre as diferenças entre esses fluxos de trabalho e diretrizes sobre como escolher o melhor para seu cenário, consulte Fluxos de trabalho de desenvolvimento do Entity Framework.

MVC

O aplicativo de exemplo é criado em ASP.NET MVC. Se você preferir trabalhar com o modelo de ASP.NET Web Forms, consulte a série de tutoriais Model Binding e Web Forms e ASP.NET Mapa de Conteúdo de Acesso a Dados.

Versões de software

Mostrado no tutorial Também funciona com
Windows 8 Windows 7
Visual Studio 2012 Visual Studio 2012 Express para Web. Isso será instalado automaticamente pelo SDK do Windows Azure se você ainda não tiver o VS 2012 ou o VS 2012 Express for Web. Visual Studio 2013 deve funcionar, mas o tutorial não foi testado com ele e algumas seleções de menu e caixas de diálogo são diferentes. A versão do VS 2013 do SDK do Windows Azure é necessária para a implantação do Windows Azure.
.NET 4.5 A maioria dos recursos mostrados funcionará no .NET 4, mas alguns não funcionarão. Por exemplo, o suporte à enumeração no EF requer o .NET 4.5.
Entity Framework 5
SDK do Windows Azure 2.1 Se você ignorar as etapas de implantação do Windows Azure, não precisará do SDK. Quando uma nova versão do SDK for lançada, o link instalará a versão mais recente. Nesse caso, talvez seja necessário adaptar algumas das instruções para novos recursos e interface do usuário.

Perguntas

Se você tiver dúvidas que não estão diretamente relacionadas ao tutorial, poderá postá-las no fórum do ASP.NET Entity Framework, no Entity Framework e no fórum do LINQ to Entities ou StackOverflow.com.

Agradecimentos

Confira o último tutorial da série para obter confirmações e uma observação sobre o VB.

O Aplicativo Web da Contoso University

O aplicativo que você criará nestes tutoriais é um site simples de uma universidade.

Os usuários podem exibir e atualizar informações de alunos, cursos e instrutores. Estas são algumas das telas que você criará.

Students_Index_page

Capturas de tela que mostram a página de pesquisa Alunos do aplicativo Web da Contoso University de exemplo e a página Criar Novo Aluno.

O estilo de interface do usuário desse site foi mantido perto do que é gerado pelos modelos internos, de modo que o tutorial possa se concentrar principalmente em como usar o Entity Framework.

Pré-requisitos

As instruções e capturas de tela neste tutorial pressupõem que você esteja usando o Visual Studio 2012 ou o Visual Studio 2012 Express para Web, com a atualização mais recente e o SDK do Azure para .NET instalados a partir de julho de 2013. Você pode obter tudo isso com o seguinte link:

SDK do Azure para .NET (Visual Studio 2012)

Se você tiver o Visual Studio instalado, o link acima instalará todos os componentes ausentes. Se você não tiver o Visual Studio, o link instalará o Visual Studio 2012 Express para Web. Você pode usar Visual Studio 2013, mas alguns dos procedimentos e telas necessários serão diferentes.

Criar um aplicativo Web MVC

Abra o Visual Studio e crie um novo projeto em C# chamado "ContosoUniversity" usando o modelo de aplicativo Web ASP.NET MVC 4 . Certifique-se de direcionar .NET Framework 4.5 (você usará enum propriedades e isso requer o .NET 4.5).

New_project_dialog_box

Na caixa de diálogo Novo projeto ASP.NET MVC 4 , selecione o modelo Aplicativo da Internet .

Deixe o mecanismo de exibição razor selecionado e deixe a caixa Criar um projeto de teste de unidade marcar desmarcada.

Clique em OK.

Project_template_options

Configurar o estilo do site

Algumas alterações simples configurarão o menu do site, o layout e a home page.

Abra Views\Shared\_Layout.cshtml e substitua o conteúdo do arquivo pelo código a seguir. As alterações são realçadas.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>@ViewBag.Title - Contoso University</title>
        <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <meta name="viewport" content="width=device-width" />
        @Styles.Render("~/Content/css")
        @Scripts.Render("~/bundles/modernizr")
    </head>
    <body>
        <header>
            <div class="content-wrapper">
                <div class="float-left">
                    <p class="site-title">@Html.ActionLink("Contoso University", "Index", "Home")</p>
                </div>
                <div class="float-right">
                    <section id="login">
                        @Html.Partial("_LoginPartial")
                    </section>
                    <nav>
                        <ul id="menu">
                            <li>@Html.ActionLink("Home", "Index", "Home")</li>
                            <li>@Html.ActionLink("About", "About", "Home")</li>
                            <li>@Html.ActionLink("Students", "Index", "Student")</li>
                            <li>@Html.ActionLink("Courses", "Index", "Course")</li>
                            <li>@Html.ActionLink("Instructors", "Index", "Instructor")</li>
                            <li>@Html.ActionLink("Departments", "Index", "Department")</li>
                        </ul>
                    </nav>
                </div>
            </div>
        </header>
        <div id="body">
            @RenderSection("featured", required: false)
            <section class="content-wrapper main-content clear-fix">
                @RenderBody()
            </section>
        </div>
        <footer>
            <div class="content-wrapper">
                <div class="float-left">
                    <p>&copy; @DateTime.Now.Year - Contoso University</p>
                </div>
            </div>
        </footer>

        @Scripts.Render("~/bundles/jquery")
        @RenderSection("scripts", required: false)
    </body>
</html>

Este código faz as seguintes alterações:

  • Substitui as instâncias de modelo de "My ASP.NET MVC Application" e "your logo here" por "Contoso University".
  • Adiciona vários links de ação que serão usados posteriormente no tutorial.

Em Views\Home\Index.cshtml, substitua o conteúdo do arquivo pelo código a seguir para eliminar os parágrafos de modelo sobre ASP.NET e MVC:

@{
    ViewBag.Title = "Home Page";
}
@section featured {
    <section class="featured">
        <div class="content-wrapper">
            <hgroup class="title">
                <h1>@ViewBag.Title.</h1>
                <h2>@ViewBag.Message</h2>
            </hgroup>
        </div>
    </section>
}

Em Controllers\HomeController.cs, altere o valor de ViewBag.Message no Index método Action para "Bem-vindo à Contoso University!", conforme mostrado no exemplo a seguir:

public ActionResult Index()
{
    ViewBag.Message = "Welcome to Contoso University";

    return View();
}

Pressione CTRL+F5 para executar o site. Você verá a home page com o menu main.

Contoso_University_home_page

Criar o modelo de dados

Em seguida, você criará as classes de entidade para o aplicativo Contoso University. Você começará com as três entidades a seguir:

Class_diagram

Há uma relação um-para-muitos entre as entidades Student e Enrollment, e uma relação um-para-muitos entre as entidades Course e Enrollment. Em outras palavras, um aluno pode ser registrado em qualquer quantidade de cursos e um curso pode ter qualquer quantidade de alunos registrados.

Nas seções a seguir, você criará uma classe para cada uma dessas entidades.

Observação

Se você tentar compilar o projeto antes de concluir a criação de todas essas classes de entidade, receberá erros do compilador.

A Entidade do Aluno

Student_entity

Na pasta Modelos , crie Student.cs e substitua o código existente pelo seguinte código:

using System;
using System.Collections.Generic;

namespace ContosoUniversity.Models
{
    public class Student
    {
        public int StudentID { get; set; }
        public string LastName { get; set; }
        public string FirstMidName { get; set; }
        public DateTime EnrollmentDate { get; set; }
        
        public virtual ICollection<Enrollment> Enrollments { get; set; }
    }
}

A propriedade StudentID se tornará 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 chamada ID ou classnameID como a chave primária.

A propriedade Enrollments é uma propriedade de navegação. As propriedades de navegação armazenam outras entidades que estão relacionadas a essa entidade. Nesse caso, a Enrollments propriedade de uma Student entidade manterá todas as Enrollment entidades relacionadas a essa Student entidade. Em outras palavras, se uma determinada Student linha no banco de dados tiver duas linhas relacionadas Enrollment (linhas que contêm o valor da chave primária desse aluno em sua StudentID coluna de chave estrangeira), a Student propriedade de navegação dessa Enrollments entidade conterá essas duas Enrollment entidades.

As propriedades de navegação normalmente são definidas como virtual para que possam aproveitar determinadas funcionalidades do Entity Framework, como o carregamento lento. (O carregamento lento será explicado posteriormente, no tutorial Lendo dados relacionados mais adiante nesta série.

Se uma propriedade de navegação pode armazenar várias entidades (como em relações muitos para muitos ou um-para-muitos), o tipo precisa ser uma lista na qual entradas podem ser adicionadas, excluídas e atualizadas, como ICollection.

A Entidade de Registro

Enrollment_entity

Na pasta Models, crie Enrollment.cs e substitua o código existente pelo seguinte código:

namespace ContosoUniversity.Models
{
    public enum Grade
    {
        A, B, C, D, F
    }

    public class Enrollment
    {
        public int EnrollmentID { get; set; }
        public int CourseID { get; set; }
        public int StudentID { get; set; }
        public Grade? Grade { get; set; }
        
        public virtual Course Course { get; set; }
        public virtual Student Student { get; set; }
    }
}

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

A propriedade StudentID é uma chave estrangeira e a propriedade de navegação correspondente é Student. Uma entidade Enrollment é associada a uma entidade Student, de modo que a propriedade possa armazenar apenas uma única entidade Student (ao contrário da propriedade de navegação Student.Enrollments que você viu anteriormente, que pode armazenar várias entidades Enrollment).

A propriedade CourseID é uma chave estrangeira e a propriedade de navegação correspondente é Course. Uma entidade Enrollment está associada a uma entidade Course.

A entidade Course

Course_entity

Na pasta Modelos , crie Course.cs, substituindo o código existente pelo seguinte código:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
    public class Course
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int CourseID { get; set; }
        public string Title { get; set; }
        public int Credits { get; set; }
        
        public virtual ICollection<Enrollment> Enrollments { get; set; }
    }
}

A propriedade Enrollments é uma propriedade de navegação. Uma entidade Course pode estar relacionada a qualquer quantidade de entidades Enrollment.

Vamos dizer mais sobre o [DatabaseGenerated(DatabaseGeneratedOption. Nenhum)] atributo no próximo tutorial. Basicamente, esse atributo permite que você insira a chave primária do curso, em vez de fazer com que ela seja gerada pelo banco de dados.

Criar o contexto de banco de dados

A classe main que coordena a funcionalidade do Entity Framework para um determinado modelo de dados é a classe de contexto do banco de dados. Você cria essa classe derivando da classe System.Data.Entity.DbContext . No código, especifique quais entidades são incluídas no modelo de dados. Também personalize o comportamento específico do Entity Framework. Neste projeto, a classe é chamada SchoolContext.

Crie uma pasta chamada DAL (para Camada de Acesso a Dados). Nessa pasta, crie um novo arquivo de classe chamado SchoolContext.cs e substitua o código existente pelo seguinte código:

using ContosoUniversity.Models;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;

namespace ContosoUniversity.DAL
{
    public class SchoolContext : DbContext
    {
        public DbSet<Student> Students { get; set; }
        public DbSet<Enrollment> Enrollments { get; set; }
        public DbSet<Course> Courses { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }
    }
}

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

A modelBuilder.Conventions.Remove instrução no método OnModelCreating impede que nomes de tabela sejam pluralizados. Se você não fizesse isso, as tabelas geradas seriam chamadas Studentsde , Coursese Enrollments. Em vez disso, os nomes de tabela serão Student, Coursee Enrollment. Os desenvolvedores não concordam sobre se os nomes de tabela devem ser pluralizados ou não. Este tutorial usa o formulário singular, mas o ponto importante é que você pode selecionar qualquer formulário que preferir incluindo ou omitindo essa linha de código.

SQL Server Express LocalDB

LocalDB é uma versão leve do Mecanismo de Banco de Dados SQL Server Express que começa sob demanda e é executado no modo de usuário. O LocalDB é executado em um modo de execução especial de SQL Server Express que permite trabalhar com bancos de dados como arquivos .mdf. Normalmente, os arquivos de banco de dados LocalDB são mantidos na pasta App_Data de um projeto Web. O recurso de instância de usuário no SQL Server Express também permite que você trabalhe com arquivos .mdf, mas o recurso de instância do usuário foi preterido; portanto, o LocalDB é recomendado para trabalhar com arquivos .mdf.

Normalmente, SQL Server Express não é usado para aplicativos Web de produção. O LocalDB, em particular, não é recomendado para uso em produção com um aplicativo Web porque ele não foi projetado para funcionar com o IIS.

No Visual Studio 2012 e versões posteriores, o LocalDB é instalado por padrão com o Visual Studio. No Visual Studio 2010 e versões anteriores, SQL Server Express (sem LocalDB) é instalado por padrão com o Visual Studio; você precisa instalá-lo manualmente se estiver usando o Visual Studio 2010.

Neste tutorial, você trabalhará com o LocalDB para que o banco de dados possa ser armazenado na pasta App_Data como um arquivo .mdf . Abra o arquivo deWeb.config raiz e adicione uma nova cadeia de conexão à connectionStrings coleção, conforme mostrado no exemplo a seguir. (Atualize o arquivo Web.config na pasta raiz do projeto. Há também um arquivo Web.config está na subpasta Views que você não precisa atualizar.)

<add name="SchoolContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=ContosoUniversity;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\ContosoUniversity.mdf" providerName="System.Data.SqlClient" />

Por padrão, o Entity Framework procura um cadeia de conexão chamado igual à DbContext classe (SchoolContext para este projeto). O cadeia de conexão que você adicionou especifica um banco de dados LocalDB chamado ContosoUniversity.mdf localizado na pasta App_Data. Para obter mais informações, consulte SQL Server Cadeias de conexão para aplicativos Web ASP.NET.

Na verdade, você não precisa especificar o cadeia de conexão. Se você não fornecer um cadeia de conexão, o Entity Framework criará um para você; no entanto, o banco de dados pode não estar na pasta App_data do aplicativo. Para obter informações sobre onde o banco de dados será criado, consulte Código Primeiro para um Novo Banco de Dados.

A connectionStrings coleção também tem um cadeia de conexão chamado DefaultConnection que é usado para o banco de dados de associação. Você não usará o banco de dados de associação neste tutorial. A única diferença entre as duas cadeias de conexão é o nome do banco de dados e o valor do atributo de nome.

Configurar e executar uma primeira migração de código

Quando você começa a desenvolver um aplicativo pela primeira vez, seu modelo de dados é alterado com frequência e sempre que o modelo é alterado, ele fica fora de sincronia com o banco de dados. Você pode configurar o Entity Framework para remover e recriar automaticamente o banco de dados sempre que alterar o modelo de dados. Isso não é um problema no início do desenvolvimento porque os dados de teste são facilmente recriados, mas depois de ter implantado na produção, você geralmente deseja atualizar o esquema de banco de dados sem descartar o banco de dados. O recurso Migrações permite que o Code First atualize o banco de dados sem descartar e recriar o banco de dados. No início do ciclo de desenvolvimento de um novo projeto, talvez você queira usar DropCreateDatabaseIfModelChanges para remover, recriar e propagar novamente o banco de dados sempre que o modelo for alterado. Se você se preparar para implantar seu aplicativo, poderá converter para a abordagem de migrações. Para este tutorial, você usará apenas migrações. Para obter mais informações, consulte Migrações do Code First e Migrations Screencast Series.

Habilitar as Migrações Code First

  1. No menu Ferramentas , clique em Gerenciador de Pacotes NuGet e, em seguida, Console do Gerenciador de Pacotes.

    Selecting_Package_Manager_Console

  2. PM> No prompt, insira o seguinte comando:

    enable-migrations -contexttypename SchoolContext
    

    Comando enable-migrations

    Esse comando cria uma pasta Migrações no projeto ContosoUniversity e coloca nessa pasta um arquivo Configuration.cs que você pode editar para configurar as Migrações.

    Pasta Migrações

    A Configuration classe inclui um Seed método chamado quando o banco de dados é criado e sempre que ele é atualizado após uma alteração de modelo de dados.

    internal sealed class Configuration : DbMigrationsConfiguration<ContosoUniversity.Models.SchoolContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
        }
    
        protected override void Seed(ContosoUniversity.Models.SchoolContext context)
        {
            //  This method will be called after migrating to the latest version.
    
            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //
        }
    }
    

    A finalidade desse Seed método é permitir que você insira dados de teste no banco de dados depois que o Code First os criar ou atualizá-los.

Configurar o método Seed

O método Seed é executado quando Migrações do Code First cria o banco de dados e sempre que atualiza o banco de dados para a migração mais recente. A finalidade do método Seed é permitir que você insira dados em suas tabelas antes que o aplicativo acesse o banco de dados pela primeira vez.

Em versões anteriores do Code First, antes do lançamento das Migrações, era comum Seed que os métodos inserissem dados de teste, pois a cada alteração de modelo durante o desenvolvimento o banco de dados precisava ser completamente excluído e recriado do zero. Com Migrações do Code First, os dados de teste são retidos após alterações no banco de dados, portanto, a inclusão de dados de teste no método Seed normalmente não é necessária. Na verdade, você não deseja que o Seed método insira dados de teste se estiver usando Migrações para implantar o banco de dados em produção, pois o Seed método será executado em produção. Nesse caso, você deseja que o Seed método insira no banco de dados apenas os dados que você deseja inserir na produção. Por exemplo, talvez você queira que o banco de dados inclua nomes de departamento reais na Department tabela quando o aplicativo ficar disponível em produção.

Para este tutorial, você usará Migrações para implantação, mas seu Seed método inserirá dados de teste de qualquer maneira para facilitar a visualização de como a funcionalidade do aplicativo funciona sem precisar inserir manualmente muitos dados.

  1. Substitua o conteúdo do arquivo Configuration.cs pelo código a seguir, que carregará dados de teste no novo banco de dados.

    namespace ContosoUniversity.Migrations
    {
       using System;
       using System.Collections.Generic;
       using System.Data.Entity.Migrations;
       using System.Linq;
       using ContosoUniversity.Models;
    
       internal sealed class Configuration : DbMigrationsConfiguration<ContosoUniversity.DAL.SchoolContext>
       {
          public Configuration()
          {
             AutomaticMigrationsEnabled = false;
          }
    
          protected override void Seed(ContosoUniversity.DAL.SchoolContext context)
          {
             var students = new List<Student>
                {
                    new Student { FirstMidName = "Carson",   LastName = "Alexander", 
                        EnrollmentDate = DateTime.Parse("2010-09-01") },
                    new Student { FirstMidName = "Meredith", LastName = "Alonso",    
                        EnrollmentDate = DateTime.Parse("2012-09-01") },
                    new Student { FirstMidName = "Arturo",   LastName = "Anand",     
                        EnrollmentDate = DateTime.Parse("2013-09-01") },
                    new Student { FirstMidName = "Gytis",    LastName = "Barzdukas", 
                        EnrollmentDate = DateTime.Parse("2012-09-01") },
                    new Student { FirstMidName = "Yan",      LastName = "Li",        
                        EnrollmentDate = DateTime.Parse("2012-09-01") },
                    new Student { FirstMidName = "Peggy",    LastName = "Justice",   
                        EnrollmentDate = DateTime.Parse("2011-09-01") },
                    new Student { FirstMidName = "Laura",    LastName = "Norman",    
                        EnrollmentDate = DateTime.Parse("2013-09-01") },
                    new Student { FirstMidName = "Nino",     LastName = "Olivetto",  
                        EnrollmentDate = DateTime.Parse("2005-08-11") }
                };
             students.ForEach(s => context.Students.AddOrUpdate(p => p.LastName, s));
             context.SaveChanges();
    
             var courses = new List<Course>
                {
                    new Course {CourseID = 1050, Title = "Chemistry",      Credits = 3, },
                    new Course {CourseID = 4022, Title = "Microeconomics", Credits = 3, },
                    new Course {CourseID = 4041, Title = "Macroeconomics", Credits = 3, },
                    new Course {CourseID = 1045, Title = "Calculus",       Credits = 4, },
                    new Course {CourseID = 3141, Title = "Trigonometry",   Credits = 4, },
                    new Course {CourseID = 2021, Title = "Composition",    Credits = 3, },
                    new Course {CourseID = 2042, Title = "Literature",     Credits = 4, }
                };
             courses.ForEach(s => context.Courses.AddOrUpdate(p => p.Title, s));
             context.SaveChanges();
    
             var enrollments = new List<Enrollment>
                {
                    new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Alexander").StudentID, 
                        CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID, 
                        Grade = Grade.A 
                    },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Alexander").StudentID,
                        CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID, 
                        Grade = Grade.C 
                     },                            
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Alexander").StudentID,
                        CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID, 
                        Grade = Grade.B
                     },
                     new Enrollment { 
                         StudentID = students.Single(s => s.LastName == "Alonso").StudentID,
                        CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID, 
                        Grade = Grade.B 
                     },
                     new Enrollment { 
                         StudentID = students.Single(s => s.LastName == "Alonso").StudentID,
                        CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID, 
                        Grade = Grade.B 
                     },
                     new Enrollment {
                        StudentID = students.Single(s => s.LastName == "Alonso").StudentID,
                        CourseID = courses.Single(c => c.Title == "Composition" ).CourseID, 
                        Grade = Grade.B 
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Anand").StudentID,
                        CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Anand").StudentID,
                        CourseID = courses.Single(c => c.Title == "Microeconomics").CourseID,
                        Grade = Grade.B         
                     },
                    new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Barzdukas").StudentID,
                        CourseID = courses.Single(c => c.Title == "Chemistry").CourseID,
                        Grade = Grade.B         
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Li").StudentID,
                        CourseID = courses.Single(c => c.Title == "Composition").CourseID,
                        Grade = Grade.B         
                     },
                     new Enrollment { 
                        StudentID = students.Single(s => s.LastName == "Justice").StudentID,
                        CourseID = courses.Single(c => c.Title == "Literature").CourseID,
                        Grade = Grade.B         
                     }
                };
    
             foreach (Enrollment e in enrollments)
             {
                var enrollmentInDataBase = context.Enrollments.Where(
                    s =>
                         s.Student.StudentID == e.StudentID &&
                         s.Course.CourseID == e.CourseID).SingleOrDefault();
                if (enrollmentInDataBase == null)
                {
                   context.Enrollments.Add(e);
                }
             }
             context.SaveChanges();
          }
       }
    }
    

    O método Seed usa o objeto de contexto de banco de dados como um parâmetro de entrada e o código no método usa esse objeto para adicionar novas entidades ao banco de dados. Para cada tipo de entidade, o código cria uma coleção de novas entidades, as adiciona à propriedade DbSet apropriada e salva as alterações no banco de dados. Não é necessário chamar o método SaveChanges após cada grupo de entidades, como é feito aqui, mas fazer isso ajuda a localizar a origem de um problema se ocorrer uma exceção enquanto o código está gravando no banco de dados.

    Algumas das instruções que inserem dados usam o método AddOrUpdate para executar uma operação "upsert". Como o Seed método é executado a cada migração, você não pode simplesmente inserir dados, pois as linhas que você está tentando adicionar já estarão lá após a primeira migração que cria o banco de dados. A operação "upsert" impede erros que aconteceriam se você tentasse inserir uma linha que já existe, mas ela substitui quaisquer alterações nos dados que você possa ter feito durante o teste do aplicativo. Com os dados de teste em algumas tabelas, talvez você não queira que isso aconteça: em alguns casos, ao alterar dados durante o teste, você deseja que suas alterações permaneçam após as atualizações do banco de dados. Nesse caso, você deseja fazer uma operação de inserção condicional: insira uma linha somente se ela ainda não existir. O método Seed usa ambas as abordagens.

    O primeiro parâmetro passado para o método AddOrUpdate especifica a propriedade a ser usada para marcar se uma linha já existir. Para os dados do aluno de teste que você está fornecendo, a LastName propriedade pode ser usada para essa finalidade, pois cada sobrenome na lista é exclusivo:

    context.Students.AddOrUpdate(p => p.LastName, s)
    

    Esse código pressupõe que os sobrenomes sejam exclusivos. Se você adicionar manualmente um aluno com um sobrenome duplicado, obterá a seguinte exceção na próxima vez que executar uma migração.

    A sequência contém mais de um elemento

    Para obter mais informações sobre o método, consulte Tomar cuidado com o método AddOrUpdate do EF 4.3 no blog de Julie Lerman.AddOrUpdate

    O código que adiciona Enrollment entidades não usa o AddOrUpdate método . Ele verifica se uma entidade já existe e insere a entidade se ela não existe. Essa abordagem preservará as alterações feitas em uma nota de registro quando as migrações forem executadas. O código percorre cada membro da EnrollmentLista e, se o registro não for encontrado no banco de dados, ele adicionará o registro ao banco de dados. Na primeira vez que você atualizar o banco de dados, o banco de dados estará vazio, portanto, ele adicionará cada registro.

    foreach (Enrollment e in enrollments)
    {
        var enrollmentInDataBase = context.Enrollments.Where(
            s => s.Student.StudentID == e.Student.StudentID &&
                 s.Course.CourseID == e.Course.CourseID).SingleOrDefault();
        if (enrollmentInDataBase == null)
        {
            context.Enrollments.Add(e);
        }
    }
    

    Para obter informações sobre como depurar o Seed método e como lidar com dados redundantes, como dois alunos chamados "Alexander Carson", consulte Propagação e depuração de DBs do EF (Entity Framework) no blog de Rick Anderson.

  2. Compile o projeto.

Criar e executar a primeira migração

  1. Na janela Console do Gerenciador de Pacotes, insira os seguintes comandos:

    add-migration InitialCreate
    update-database
    

    Captura de tela que mostra a janela Console do Gerenciador de Pacotes. Os comandos adicionam o sublinhado de migração de hífen Inicial Criar e atualizar o banco de dados de hífen estão realçados.

    O add-migration comando adiciona à pasta Migrações um arquivo [DateStamp]_InitialCreate.cs que contém o código que cria o banco de dados. O primeiro parâmetro (InitialCreate) é usado para o nome do arquivo e pode ser o que você quiser; você normalmente escolhe uma palavra ou frase que resume o que está sendo feito na migração. Por exemplo, você pode nomear uma migração posterior "AddDepartmentTable".

    Pasta de migrações com migração inicial

    O Up método da InitialCreate classe cria as tabelas de banco de dados que correspondem aos conjuntos de entidades do modelo de dados e o método as Down exclui. As migrações chamam o método Up para implementar as alterações do modelo de dados para uma migração. Quando você insere um comando para reverter a atualização, as Migrações chamam o método Down. O código a seguir mostra o conteúdo do InitialCreate arquivo:

    namespace ContosoUniversity.Migrations
    {
        using System;
        using System.Data.Entity.Migrations;
        
        public partial class InitialCreate : DbMigration
        {
            public override void Up()
            {
                CreateTable(
                    "dbo.Student",
                    c => new
                        {
                            StudentID = c.Int(nullable: false, identity: true),
                            LastName = c.String(),
                            FirstMidName = c.String(),
                            EnrollmentDate = c.DateTime(nullable: false),
                        })
                    .PrimaryKey(t => t.StudentID);
                
                CreateTable(
                    "dbo.Enrollment",
                    c => new
                        {
                            EnrollmentID = c.Int(nullable: false, identity: true),
                            CourseID = c.Int(nullable: false),
                            StudentID = c.Int(nullable: false),
                            Grade = c.Int(),
                        })
                    .PrimaryKey(t => t.EnrollmentID)
                    .ForeignKey("dbo.Course", t => t.CourseID, cascadeDelete: true)
                    .ForeignKey("dbo.Student", t => t.StudentID, cascadeDelete: true)
                    .Index(t => t.CourseID)
                    .Index(t => t.StudentID);
                
                CreateTable(
                    "dbo.Course",
                    c => new
                        {
                            CourseID = c.Int(nullable: false),
                            Title = c.String(),
                            Credits = c.Int(nullable: false),
                        })
                    .PrimaryKey(t => t.CourseID);
                
            }
            
            public override void Down()
            {
                DropIndex("dbo.Enrollment", new[] { "StudentID" });
                DropIndex("dbo.Enrollment", new[] { "CourseID" });
                DropForeignKey("dbo.Enrollment", "StudentID", "dbo.Student");
                DropForeignKey("dbo.Enrollment", "CourseID", "dbo.Course");
                DropTable("dbo.Course");
                DropTable("dbo.Enrollment");
                DropTable("dbo.Student");
            }
        }
    }
    

    O update-database comando executa o Up método para criar o banco de dados e, em seguida, executa o Seed método para preencher o banco de dados.

Um banco de dados SQL Server foi criado para seu modelo de dados. O nome do banco de dados é ContosoUniversity e o arquivo .mdf está na pasta App_Data do projeto, pois é isso que você especificou em seu cadeia de conexão.

Você pode usar o Servidor Explorer ou o SSOX (SQL Server Pesquisador de Objetos) para exibir o banco de dados no Visual Studio. Para este tutorial, você usará o Explorer do Servidor. No Visual Studio Express 2012 para Web, a Explorer do Servidor é chamada de Explorer de Banco de Dados.

  1. No menu Exibir, clique em Servidor Explorer.

  2. Clique no ícone Adicionar Conexão .

    Captura de tela que mostra a janela Explorer banco de dados. O ícone Adicionar Conexão está realçado.

  3. Se você receber uma solicitação com a caixa de diálogo Escolher Fonte de Dados, clique em Microsoft SQL Server e, em seguida, clique em Continuar.

    Captura de tela que mostra a caixa de diálogo Escolher Fonte de Dados. A fonte de dados do Microsoft S Q L Server está selecionada.

  4. Na caixa de diálogo Adicionar Conexão , insira (localdb)\v11.0 para o Nome do Servidor. Em Selecionar ou inserir um nome de banco de dados, selecione ContosoUniversity.

    Captura de tela que mostra a caixa de diálogo Adicionar Conexão. O nome do servidor de exemplo e o banco de dados da Contoso University estão realçados.

  5. Clique em OK.

  6. Expanda SchoolContext e, em seguida, expanda Tabelas.

    Captura de tela que mostra a página Explorer servidor. As guias Contexto escolar e Tabelas são expandidas.

  7. Clique com o botão direito do mouse na tabela Student e clique em Mostrar Dados da Tabela para ver as colunas que foram criadas e as linhas que foram inseridas na tabela.

    Tabela de alunos

Criando um controlador de aluno e exibições

A próxima etapa é criar uma ASP.NET controlador MVC e exibições em seu aplicativo que podem funcionar com uma dessas tabelas.

  1. Para criar um Student controlador, clique com o botão direito do mouse na pasta Controladores no Gerenciador de Soluções, selecione Adicionar e clique em Controlador. Na caixa de diálogo Adicionar Controlador , faça as seguintes seleções e clique em Adicionar:

    • Nome do controlador: StudentController.

    • Modelo: controlador MVC com ações e exibições de leitura/gravação, usando o Entity Framework.

    • Classe de modelo: Student (ContosoUniversity.Models). (Se você não vir essa opção na lista suspensa, compile o projeto e tente novamente.)

    • Classe de contexto de dados: SchoolContext (ContosoUniversity.Models).

    • Exibições: Razor (CSHTML). (O padrão.)

      Add_Controller_dialog_box_for_Student_controller

  2. O Visual Studio abre o arquivo Controllers\StudentController.cs . Você verá que uma variável de classe foi criada que cria uma instância de um objeto de contexto de banco de dados:

    private SchoolContext db = new SchoolContext();
    

    O Index método de ação obtém uma lista de alunos da entidade Students definida lendo a Students propriedade da instância de contexto do banco de dados:

    public ViewResult Index()
    {
        return View(db.Students.ToList());
    }
    

    A exibição Student\Index.cshtml exibe esta lista em uma tabela:

    <table>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.LastName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.FirstMidName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.EnrollmentDate)
            </th>
            <th></th>
        </tr>
    
    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.LastName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FirstMidName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.EnrollmentDate)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id=item.StudentID }) |
                @Html.ActionLink("Details", "Details", new { id=item.StudentID }) |
                @Html.ActionLink("Delete", "Delete", new { id=item.StudentID })
            </td>
        </tr>
    }
    
  3. Pressione CTRL+F5 para executar o projeto.

    Clique na guia Alunos para ver os dados de teste inseridos pelo Seed método.

    Página Índice do Aluno

Convenções

A quantidade de código que você precisava escrever para que o Entity Framework pudesse criar um banco de dados completo para você é mínima devido ao uso de convenções ou suposições que o Entity Framework faz. Alguns deles já foram observados:

  • As formas pluralizadas de nomes de classe de entidade são usadas como nomes de tabela.
  • Os nomes de propriedade de entidade são usados para nomes de coluna.
  • As propriedades de entidade nomeadas ID ou classnameID são reconhecidas como propriedades de chave primária.

Você viu que as convenções podem ser substituídas (por exemplo, você especificou que os nomes de tabela não devem ser pluralizados) e aprenderá mais sobre convenções e como substituí-las no tutorial Criando um modelo de dados mais complexo mais adiante nesta série. Para obter mais informações, consulte Convenções do Code First.

Resumo

Agora você criou um aplicativo simples que usa o Entity Framework e SQL Server Express para armazenar e exibir dados. No tutorial a seguir, você aprenderá a executar operações CRUD básicas (criar, ler, atualizar, excluir). Você pode deixar comentários na parte inferior desta página. Informe-nos como você gostou dessa parte do tutorial e como podemos melhorá-la.

Os links para outros recursos do Entity Framework podem ser encontrados no Mapa de Conteúdo de Acesso a Dados do ASP.NET.