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

por Tom Dykstra

Note

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

O aplicativo Web de exemplo Contoso University demonstra como criar aplicativos ASP.NET 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 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 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 Entity Framework fluxos de trabalho de desenvolvimento.

MVC

O aplicativo de exemplo se baseia no ASP.NET MVC. Se você preferir trabalhar com o modelo de Web Forms ASP.NET, consulte a Associação de modelo e Web Forms a série de tutoriais e o mapa de conteúdo de acesso a dados do ASP.net.

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 para 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 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 terão. Por exemplo, o suporte a enum 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 a nova interface do usuário e recursos.

Perguntas

Se você tiver dúvidas que não estão diretamente relacionadas ao tutorial, poderá lançá-las no fórum de Entity Framework ASP.net, no Entity Framework e no LINQ to Entities forumou stackoverflow.com.

Agradecimentos

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

Versão original do tutorial

A versão original do tutorial está disponível no livro eletrônico do EF 4,1/MVC 3.

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

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 orientaçõ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á 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 C# chamado "ContosoUniversity" usando o modelo de aplicativo Web ASP.NET MVC 4 . Certifique-se de que você se destina .NET Framework 4,5 (você usará enum Propriedadese que requer o .NET 4,5).

New_project_dialog_box

Na caixa de diálogo novo projeto do ASP.NET MVC 4 , selecione o modelo de aplicativo da Internet .

Deixe o mecanismo de exibição do Razor selecionado e deixe a caixa de seleção criar um projeto de teste de unidade 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 "meu aplicativo MVC ASP.NET" e "seu logotipo aqui" por "Contoso University".
  • Adiciona vários links de ação que serão usados posteriormente no tutorial.

No 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>
}

No Controllers\HomeController.cs, altere o valor de ViewBag.Message no Index método de ação 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 principal.

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 seguintes entidades:

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.

Note

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

A entidade Student

Student_entity

Na pasta modelos , crie Student.cs e substitua o código existente pelo código a seguir:

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 nomeada ID ou ClassName ID 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 Enrollment linhas relacionadas (linhas que contêm o valor de chave primária do aluno em sua StudentID coluna de chave estrangeira), a Student propriedade de navegação dessa entidade Enrollments conterá essas duas Enrollment entidades.

As propriedades de navegação são normalmente definidas como virtual para que possam aproveitar determinadas funcionalidades de 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 grau é 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 classificação que é nula é diferente de uma taxa zero: null significa que uma classificação 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 código a seguir:

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 falar mais sobre o [DatabaseGenerated(DatabaseGeneratedOption. Nenhum)] 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 principal que coordena Entity Framework funcionalidade para um determinado modelo de dados é a classe de contexto do banco de dado. 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 código a seguir:

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 Entity Framework, um conjunto de entidades geralmente 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 os nomes de tabela sejam plural. Se você não fez isso, as tabelas geradas seriam nomeadas Students , Courses e Enrollments . Em vez disso, os nomes de tabela serão Student , Course e 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 esta linha de código.

SQL Server Express LocalDB

O LocalDB é uma versão leve do Mecanismo de Banco de Dados de SQL Server Express que inicia 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 que você trabalhe com bancos de dados como arquivos . MDF . Normalmente, os arquivos de banco de dados LocalDB são mantidos na pasta _ Data app 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 de 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 o LocalDB) é instalado por padrão com o Visual Studio; Você precisará 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 _ Data app como um arquivo . MDF . Abra o arquivo de Web.config raiz e adicione uma nova cadeia de conexão à connectionStrings coleção, conforme mostrado no exemplo a seguir. (Certifique-se de atualizar o arquivo de Web.config na pasta raiz do projeto. Há também um arquivo de 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, a Entity Framework procura uma cadeia de conexão denominada igual à DbContext classe ( SchoolContext para este projeto). A cadeia de conexão que você adicionou especifica um banco de dados LocalDB chamado ContosoUniversity. MDF localizado na pasta _ dados do aplicativo . Para obter mais informações, consulte SQL Server cadeias de conexão para aplicativos Web ASP.net.

Na verdade, você não precisa especificar a cadeia de conexão. Se você não fornecer uma cadeia de conexão, Entity Framework criará uma para você; no entanto, o banco de dados pode não estar na pasta _ Data app do seu aplicativo. Para obter informações sobre onde o banco de dados será criado, consulte Code First para um novo banco de dados.

A connectionStrings coleção também tem uma cadeia de conexão chamada DefaultConnection que é usada 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 Name.

Configurar e executar uma migração de Code First

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

Habilitar as Migrações Code First

  1. No menu ferramentas , clique em Gerenciador de pacotes NuGet e em console do Gerenciador de pacotes.

    Selecting_Package_Manager_Console

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

    enable-migrations -contexttypename SchoolContext
    

    comando Enable-Migrations

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

    Pasta de migrações

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

    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 dado depois que Code First o cria ou atualiza.

Configurar o método semente

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

Em versões anteriores do Code First, antes da liberação das migrações, era comum Seed os métodos inserir dados de teste, porque com cada alteração de modelo durante o desenvolvimento, o banco de dado tinha que ser completamente excluído e recriado do zero. Com o Migrações do Code First, os dados de teste são retidos após as alterações do banco de dados, de modo que, inclusive, o método de semente não é necessário normalmente. Na verdade, você não quer que o Seed método insira dados de teste se você estiver usando migrações para implantar o Database para produção, pois o Seed método será executado em produção. Nesse caso, você deseja que o método seja inserido no Seed banco de dados somente 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 se tornar disponível em produção.

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

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

    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 semente 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, adiciona-as à propriedade DbSet apropriada e salva as alterações no banco de dados. Não é necessário chamar o método SaveChanges depois de 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 estiver 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 com cada migração, você não pode apenas 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 ocorrerão se você tentar inserir uma linha que já existe, mas ela substitui quaisquer alterações nos dados que você tenha 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 os dados durante o teste, você deseja que as alterações permaneçam após as atualizações do banco. 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 semente usa ambas as abordagens.

    O primeiro parâmetro passado para o método AddOrUpdate especifica a propriedade a ser usada para verificar se já existe uma linha. Para os dados de 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 últimos nomes são 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 AddOrUpdate método, consulte tome cuidado com o método EF 4,3 AddOrUpdate no blog de Julie Lerman.

    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, caso ela não exista. Essa abordagem preservará as alterações feitas em uma classificação de registro quando as migrações são executadas. O código percorre cada membro da Enrollment lista 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 nomeados como "Alexander Carson", consulte o Entity Framework de Fe (propagação e depuração) no blog de Rick Anderson.

  2. Compile o projeto.

Criar e executar a primeira migração

  1. Na janela do console do Gerenciador de pacotes, digite os seguintes comandos:

    add-migration InitialCreate
    update-database
    

    O add-migration comando adiciona à pasta Migrations um arquivo _ InitialCreate.cs [dateStamp] 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ê desejar; normalmente, você escolhe uma palavra ou frase que resume o que está sendo feito na migração. Por exemplo, você pode nomear uma migração mais tarde como " 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 de modelo de dado e o Down método os 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 dado. O nome do banco de dados é ContosoUniversity e o arquivo . MDF está na pasta de _ dados de aplicativo do projeto, pois é isso que você especificou na cadeia de conexão.

Você pode usar o Gerenciador de servidores ou o pesquisador de objetos do SQL Server (SSOX) para exibir o banco de dados no Visual Studio. Para este tutorial, você usará Gerenciador de servidores. No Visual Studio Express 2012 para Web, Gerenciador de servidores é chamado de Gerenciador de banco de dados.

  1. No menu Exibir , clique em Gerenciador de servidores.

  2. Clique no ícone Adicionar conexão .

  3. Se você receber a caixa de diálogo escolher fonte de dados , clique em Microsoft SQL Server e em continuar.

  4. Na caixa de diálogo Adicionar conexão , digite (LocalDB) \V11.0 para o nome do servidor. Em selecionar ou inserir um nome de banco de dados, selecione ContosoUniversity.

  5. Clique em OK.

  6. Expanda SchoolContext e expanda tabelas.

  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 aluno

Criando um controlador de aluno e exibições

A próxima etapa é criar um controlador MVC ASP.NET 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 em Gerenciador de soluções, selecione Adicionar e, em seguida, 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 de leitura/gravação e exibições, usando Entity Framework.

    • Classe de modelo: aluno (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ê vê uma variável de classe criada que instancia 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 do conjunto de entidades dos alunos , 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 essa 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 Seed inseridos pelo método.

    Página de índice de estudante

Convenções

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

  • As formas pluraled 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 que são nomeadas ID ou ClassName ID são reconhecidas como propriedades de chave primária.

Você viu que as convenções podem ser substituídas (por exemplo, se você especificou que os nomes de tabela não devem estar em plural), e você 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 de 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 (criar, ler, atualizar, excluir) básicas. Você pode deixar comentários na parte inferior desta página. Informe-nos como você gostou desta parte do tutorial e como poderíamos aprimorá-la.

Links para outros recursos de Entity Framework podem ser encontrados no mapa de conteúdo de acesso a dados do ASP.net.