Criando um modelo de dados do Entity Framework para um aplicativo MVC do 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 aplicativos MVC 4 ASP.NET 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 ASP.NET Web Forms, consulte a série de tutoriais Associação de Modelos 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 para Web. O 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. Por exemplo, o suporte a 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 à nova interface do usuário e aos novos recursos. Perguntas
Se você tiver perguntas que não estejam diretamente relacionadas ao tutorial, poderá postá-las no fórum do ASP.NET Entity Framework, no fórum do Entity Framework e do LINQ to Entities ou StackOverflow.com.
Agradecimentos
Veja o último tutorial da série para agradecimentos e uma nota 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á.
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 em 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 o 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 MVC 4 do ASP.NET. Certifique-se de direcionar o .NET Framework 4.5 (você usará propriedades e isso requer o enum
.NET 4.5).
Na caixa de diálogo Projeto Novo ASP.NET MVC 4, selecione o modelo Aplicativo da Internet.
Deixe o mecanismo de exibição Razor selecionado e deixe a caixa de seleção Criar um projeto de teste de unidade desmarcada.
Clique em OK.
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>© @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.
Em Views\Home\Index.cshtml, substitua o conteúdo do arquivo pelo seguinte código 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ê vê a página inicial com o menu principal.
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:
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 terminar de criar todas essas classes de entidade, receberá erros do compilador.
A entidade estudantil
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 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 conterá 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), Student
a propriedade de navegação dessa Enrollments
entidade conterá essas duas Enrollment
entidades.
As propriedades de navegação normalmente são definidas para virtual
que possam aproveitar determinadas funcionalidades do Entity Framework, como carregamento lento. (O carregamento lento será explicado mais tarde, noTutorial 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
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 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
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
.
Falaremos mais sobre o [DatabaseGenerated(DatabaseGeneratedOption. None)] 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 a funcionalidade do Entity Framework para um determinado modelo de dados é a classe de contexto de 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 os nomes de tabela sejam pluralizados. Se você não fizer isso, as tabelas geradas serão nomeadas Students
, Courses
e Enrollments
. Em vez disso, os nomes das tabelas 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 a forma singular, mas o ponto importante é que você pode selecionar a forma de sua preferência incluindo ou omitindo essa linha de código.
SQL Server Express LocalDB
O LocalDB é uma versão leve do Mecanismo de Banco de Dados SQL Server Express que é iniciado sob demanda e executado no modo de usuário. O LocalDB é executado em um modo de execução especial do SQL Server Express que permite que você trabalhe com bancos de dados como arquivos .mdf . Normalmente, os arquivos de banco de dados do 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 de usuário foi preterido; portanto, o LocalDB é recomendado para trabalhar com arquivos .mdf .
Normalmente, o 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 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, o 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 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 Web.config na pasta raiz do projeto. Há também um arquivo Web.config 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 uma cadeia de conexão com o mesmo nome da 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 App_Data . Para obter mais informações, consulte Cadeias de conexão do SQL Server 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, o Entity Framework criará uma para você; No entanto, o banco de dados pode não estar na pasta App_data 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 do Code First
Quando você começa a desenvolver um aplicativo, seu modelo de dados muda com frequência e, cada vez que o modelo é alterado, ele fica fora de sincronia com o banco de dados. Você pode configurar o Entity Framework para descartar 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 implantar 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 descartá-lo e recriá-lo. No início do ciclo de desenvolvimento de um novo projeto, talvez você queira usar DropCreateDatabaseIfModelChanges para descartar, recriar e propagar novamente o banco de dados sempre que o modelo for alterado. Depois de se preparar para implantar seu aplicativo, você pode 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 Série de screencast de migrações.
Habilitar as Migrações Code First
No menu Ferramentas, clique em Gerenciador de Pacotes NuGet e, em seguida, em Console do Gerenciador de Pacotes.
No prompt,
PM>
digite o seguinte comando:enable-migrations -contexttypename SchoolContext
Esse comando cria uma pasta Migrações no projeto ContosoUniversity e coloca nessa pasta um arquivo Configuration.cs que você pode editar para configurar Migrações.
A
Configuration
classe inclui umSeed
método que é chamado quando o banco de dados é criado e sempre que é atualizado após uma alteração no 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 cria ou atualiza.
Configurar o método de semente
O método Seed é executado quando as Migrações do Code First criam o banco de dados e sempre que ele 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.
Nas 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 as Migrações do Code First, os dados de teste são retidos após as alterações do 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 na 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 estiver 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.
Substitua o conteúdo do arquivo Configuration.cs pelo código a seguir, que carregará os 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 do 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 após cada grupo de entidades, como é feito aqui, mas 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 simplesmente inserir dados, porque 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" evita erros que ocorreriam se você tentasse inserir uma linha que já existe, mas substitui quaisquer alterações nos dados que você possa ter feito durante o teste do aplicativo. Com dados de teste em algumas tabelas, talvez você não queira que isso aconteça: em alguns casos, quando você altera dados durante o teste, 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 verificar se uma linha já existe. 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 são exclusivos. Se você adicionar manualmente um aluno com um sobrenome duplicado, receberá 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 Cuidar do método AddOrUpdate do EF 4.3 no blog de Julie Lerman.O código que adiciona
Enrollment
entidades não usa oAddOrUpdate
método. Ele verifica se uma entidade já existe e insere a entidade se ela não existir. Essa abordagem preservará as alterações feitas em uma nota de registro quando as migrações forem executadas. O código percorre cada membro daEnrollment
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 chamados "Alexander Carson", consulte Propagação e depuração de bancos de dados do EF (Entity Framework) no blog de Rick Anderson.Compile o projeto.
Criar e executar a primeira migração
Na janela Console do Gerenciador de Pacotes, insira os seguintes comandos:
add-migration InitialCreate update-database
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".O
Up
método da classe cria as tabelas de banco deInitialCreate
dados que correspondem aos conjuntos de entidades do modelo de dados e oDown
método as exclui. As migrações chamam o métodoUp
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étodoDown
. O código a seguir mostra o conteúdo doInitialCreate
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 oUp
método para criar o banco de dados e, em seguida, executa oSeed
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 porque é isso que você especificou na cadeia de conexão.
Você pode usar o Gerenciador de Servidores ou o SSOX (Pesquisador de Objetos do SQL Server) para exibir o banco de dados no Visual Studio. Para este tutorial, você usará o Gerenciador de Servidores. No Visual Studio Express 2012 para Web, o Gerenciador de Servidores é chamado de Gerenciador de Banco de Dados.
No menu Exibir , clique em Gerenciador de Servidores.
Clique no ícone Adicionar conexão .
Se for solicitada a caixa de diálogo Escolher Fonte de Dados, clique em Microsoft SQL Server e, em seguida, clique em Continuar.
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.
Clique em OK.
Expanda SchoolContext e, em seguida, expanda Tabelas.
Clique com o botão direito do mouse na tabela Aluno e clique em Mostrar Dados da Tabela para ver as colunas que foram criadas e as linhas que foram inseridas na tabela.
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 possam funcionar com uma dessas tabelas.
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, crie o projeto e tente novamente.)
Classe de contexto de dados: SchoolContext (ContosoUniversity.Models).
Visualizações: Razor (CSHTML). (O padrão.)
O Visual Studio abre o arquivo Controllers\StudentController.cs . Você vê que foi criada uma variável de classe 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 Students lendo aStudents
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> }
Pressione CTRL+F5 para executar o projeto.
Clique na guia Alunos para ver os dados de teste inseridos pelo
Seed
método.
Convenções
A quantidade de código que você teve que 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 o SQL Server Express para armazenar e exibir dados. No tutorial a seguir, você aprenderá a executar operações básicas de CRUD (criar, ler, atualizar, excluir). Você pode deixar comentários na parte inferior desta página. Por favor, deixe-nos saber se você gostou desta parte do tutorial e como podemos melhorá-lo.
Links para outros recursos do Entity Framework podem ser encontrados no Mapa de Conteúdo de Acesso a Dados do ASP.NET.