Introdução com o Entity Framework 4.0 Database First e ASP.NET 4 Web Forms – Parte 2
por Tom Dykstra
O aplicativo Web de exemplo da Contoso University demonstra como criar aplicativos ASP.NET Web Forms usando o Entity Framework 4.0 e o Visual Studio 2010. Para obter informações sobre a série de tutoriais, consulte o primeiro tutorial da série
O controle EntityDataSource
No tutorial anterior, você criou um site, um banco de dados e um modelo de dados. Neste tutorial, você trabalha com o EntityDataSource
controle que ASP.NET fornece para facilitar o trabalho com um modelo de dados do Entity Framework. Você criará um GridView
controle para exibir e editar dados dos alunos, um DetailsView
controle para adicionar novos alunos e um DropDownList
controle para selecionar um departamento (que você usará posteriormente para exibir cursos associados).
Observe que neste aplicativo você não adicionará validação de entrada a páginas que atualizam o banco de dados, e parte da manipulação de erros não será tão robusta quanto seria necessário em um aplicativo de produção. Isso mantém o tutorial focado no Entity Framework e impede que ele fique muito longo. Para obter detalhes sobre como adicionar esses recursos ao seu aplicativo, consulte Validando a entrada do usuário em Páginas da Web do ASP.NET e Tratamento de Erros em páginas e aplicativos ASP.NET.
Adicionando e configurando o controle EntityDataSource
Você começará configurando um EntityDataSource
controle para ler Person
entidades do People
conjunto de entidades.
Verifique se você está com o Visual Studio aberto e se está trabalhando com o projeto criado na parte 1. Se você não criou o projeto desde que criou o modelo de dados ou desde a última alteração feita nele, compile o projeto agora. As alterações no modelo de dados não são disponibilizadas para o designer até que o projeto seja criado.
Crie uma nova página da Web usando o formulário da Web usando o modelo de Página Mestra e nomeie-a como Students.aspx.
Especifique Site.Master como a página master. Todas as páginas criadas para esses tutoriais usarão esta página master.
No modo de exibição Origem , adicione um h2
título ao Content
controle chamado Content2
, conforme mostrado no exemplo a seguir:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Student List</h2>
</asp:Content>
Na guia Dados da Caixa de Ferramentas, arraste um EntityDataSource
controle para a página, solte-o abaixo do título e altere a ID para StudentsEntityDataSource
:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Student List</h2>
<asp:EntityDataSource ID="StudentsEntityDataSource" runat="server">
</asp:EntityDataSource>
</asp:Content>
Alterne para o modo design , clique na marca inteligente do controle da fonte de dados e clique em Configurar Fonte de Dados para iniciar o assistente Configurar Fonte de Dados .
Na etapa do assistente Configurar ObjectContext, selecioneSchoolEntities como o valor de Conexão Nomeada e Selecione SchoolEntities como o valor DefaultContainerName . Em seguida, clique em Próximo.
Observação: se você receber a caixa de diálogo a seguir neste ponto, precisará compilar o projeto antes de continuar.
Na etapa Configurar Seleção de Dados, selecionePessoas como o valor de EntitySetName. Em Selecionar, verifique se a caixa Selecionar Um marcar será selecionada. Em seguida, selecione as opções para habilitar a atualização e a exclusão. Quando terminar, clique em Concluir.
Configurando regras de banco de dados para permitir a exclusão
Você criará uma página que permite que os usuários excluam os alunos da Person
tabela, que tem três relações com outras tabelas (Course
, StudentGrade
e OfficeAssignment
). Por padrão, o banco de dados impedirá que você exclua uma linha no Person
se houver linhas relacionadas em uma das outras tabelas. Você pode excluir manualmente as linhas relacionadas primeiro ou configurar o banco de dados para excluí-las automaticamente ao excluir uma Person
linha. Para registros de alunos neste tutorial, você configurará o banco de dados para excluir os dados relacionados automaticamente. Como os alunos podem ter linhas relacionadas apenas na StudentGrade
tabela, você precisa configurar apenas uma das três relações.
Se você estiver usando o arquivo School.mdf baixado do projeto que acompanha este tutorial, ignore esta seção porque essas alterações de configuração já foram feitas. Se você criou o banco de dados executando um script, configure o banco de dados executando os procedimentos a seguir.
No Server Explorer, abra o diagrama de banco de dados que você criou na parte 1. Clique com o botão direito do mouse na relação entre Person
e StudentGrade
(a linha entre tabelas) e selecione Propriedades.
Na janela Propriedades , expanda ESPECIFICAÇÃO INSERT e UPDATE e defina a propriedade DeleteRule como Cascade.
Salve e feche o diagrama. Se for perguntado se deseja atualizar o banco de dados, clique em Sim.
Para garantir que o modelo mantenha as entidades que estão na memória em sincronia com o que o banco de dados está fazendo, você deve definir regras correspondentes no modelo de dados. Abra SchoolModel.edmx, clique com o botão direito do mouse na linha de associação entre Person
e StudentGrade
e selecione Propriedades.
Na janela Propriedades , defina End1 OnDelete como Cascade.
Salve e feche o arquivo SchoolModel.edmx e recompile o projeto.
Em geral, quando o banco de dados é alterado, você tem várias opções de como sincronizar o modelo:
- Para determinados tipos de alterações (como adicionar ou atualizar tabelas, exibições ou procedimentos armazenados), clique com o botão direito do mouse no designer e selecione Atualizar Modelo do Banco de Dados para que o designer faça as alterações automaticamente.
- Regenerar o modelo de dados.
- Faça atualizações manuais como esta.
Nesse caso, você poderia ter regenerado o modelo ou atualizado as tabelas afetadas pela alteração da relação, mas, em seguida, teria que fazer o nome do campo mudar novamente (de FirstName
para FirstMidName
).
Usando um controle GridView para ler e atualizar entidades
Nesta seção, você usará um GridView
controle para exibir, atualizar ou excluir alunos.
Abra ou alterne para Students.aspx e alterne para o modo design . Na guia Dados da Caixa de Ferramentas, arraste um GridView
controle para a direita do controle, nomeie-o EntityDataSource
StudentsGridView
, clique na marca inteligente e selecione StudentsEntityDataSource como a fonte de dados.
Clique em Atualizar Esquema (clique em Sim se for solicitado a confirmar) e clique em Habilitar Paginação, Habilitar Classificação, Habilitar Edição e Habilitar Exclusão.
Clique em Editar Colunas.
Na caixa Campos selecionados , exclua PersonID, LastName e HireDate. Normalmente, você não exibe uma chave de registro para os usuários, a data de contratação não é relevante para os alunos e você coloca as duas partes do nome em um campo, portanto, você só precisa de um dos campos de nome.)
Selecione o campo FirstMidName e clique em Converter este campo em um TemplateField.
Faça o mesmo para EnrollmentDate.
Clique em OK e, em seguida, alterne para Exibição de origem. As alterações restantes serão mais fáceis de fazer diretamente na marcação. A GridView
marcação de controle agora se parece com o exemplo a seguir.
<asp:GridView ID="StudentsGridView" runat="server" AllowPaging="True"
AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="PersonID"
DataSourceID="StudentsEntityDataSource">
<Columns>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
<asp:TemplateField HeaderText="FirstMidName" SortExpression="FirstMidName">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("FirstMidName") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("FirstMidName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="EnrollmentDate" SortExpression="EnrollmentDate">
<EditItemTemplate>
<asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("EnrollmentDate") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%# Bind("EnrollmentDate") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
A primeira coluna após o campo de comando é um campo de modelo que atualmente exibe o primeiro nome. Altere a marcação deste campo de modelo para se parecer com o seguinte exemplo:
<asp:TemplateField HeaderText="Name" SortExpression="LastName">
<EditItemTemplate>
<asp:TextBox ID="LastNameTextBox" runat="server" Text='<%# Bind("LastName") %>'></asp:TextBox>
<asp:TextBox ID="FirstNameTextBox" runat="server" Text='<%# Bind("FirstMidName") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="LastNameLabel" runat="server" Text='<%# Eval("LastName") %>'></asp:Label>,
<asp:Label ID="FirstNameLabel" runat="server" Text='<%# Eval("FirstMidName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
No modo de exibição, dois Label
controles exibem o nome e o sobrenome. No modo de edição, duas caixas de texto são fornecidas para que você possa alterar o nome e o sobrenome. Assim como acontece com os Label
controles no modo de exibição, você usa Bind
expressões e Eval
exatamente como faria com ASP.NET controles de fonte de dados que se conectam diretamente a bancos de dados. A única diferença é que você está especificando propriedades de entidade em vez de colunas de banco de dados.
A última coluna é um campo de modelo que exibe a data de registro. Altere a marcação desse campo para se parecer com o seguinte exemplo:
<asp:TemplateField HeaderText="Enrollment Date" SortExpression="EnrollmentDate">
<EditItemTemplate>
<asp:TextBox ID="EnrollmentDateTextBox" runat="server" Text='<%# Bind("EnrollmentDate", "{0:d}") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="EnrollmentDateLabel" runat="server" Text='<%# Eval("EnrollmentDate", "{0:d}") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
No modo de exibição e edição, a cadeia de caracteres de formato "{0,d}" faz com que a data seja exibida no formato "data curta". (Seu computador pode estar configurado para exibir esse formato de forma diferente das imagens de tela mostradas neste tutorial.)
Observe que, em cada um desses campos de modelo, o designer usou uma Bind
expressão por padrão, mas você alterou isso para uma expressão Eval
nos ItemTemplate
elementos. A Bind
expressão disponibiliza os dados nas GridView
propriedades de controle caso você precise acessar os dados no código. Nesta página, você não precisa acessar esses dados no código, portanto, você pode usar Eval
, o que é mais eficiente. Para obter mais informações, consulte Obtendo seus dados dos controles de dados.
Revisão da marcação de controle EntityDataSource para melhorar o desempenho
Na marcação do EntityDataSource
controle, remova os ConnectionString
atributos e DefaultContainerName
e substitua-os por um ContextTypeName="ContosoUniversity.DAL.SchoolEntities"
atributo . Essa é uma alteração que você deve fazer sempre que criar um EntityDataSource
controle, a menos que precise usar uma conexão diferente daquela codificada na classe de contexto do objeto. O uso do ContextTypeName
atributo fornece os seguintes benefícios:
- Melhor desempenho. Quando o
EntityDataSource
controle inicializa o modelo de dados usando osConnectionString
atributos eDefaultContainerName
, ele executa trabalho adicional para carregar metadados em cada solicitação. Isso não será necessário se você especificar oContextTypeName
atributo . - O carregamento lento é ativado por padrão em classes de contexto de objeto geradas (como
SchoolEntities
neste tutorial) no Entity Framework 4.0. Isso significa que as propriedades de navegação são carregadas com dados relacionados automaticamente quando você precisa. O carregamento lento é explicado mais detalhadamente mais adiante neste tutorial. - Todas as personalizações aplicadas à classe de contexto de objeto (nesse caso, a
SchoolEntities
classe) estarão disponíveis para controles que usam oEntityDataSource
controle . Personalizar a classe de contexto de objeto é um tópico avançado que não é abordado nesta série de tutoriais. Para obter mais informações, consulte Estendendo tipos gerados pela Estrutura de Entidade.
A marcação agora será semelhante ao exemplo a seguir (a ordem das propriedades pode ser diferente):
<asp:EntityDataSource ID="StudentsEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EntitySetName="People"
EnableDelete="True" EnableUpdate="True">
</asp:EntityDataSource>
O EnableFlattening
atributo refere-se a um recurso que era necessário em versões anteriores do Entity Framework porque colunas de chave estrangeira não foram expostas como propriedades de entidade. A versão atual possibilita o uso de associações de chave estrangeira, o que significa que as propriedades de chave estrangeira são expostas para todas, menos para muitas associações. Se suas entidades tiverem propriedades de chave estrangeira e nenhum tipo complexo, você poderá deixar esse atributo definido como False
. Não remova o atributo da marcação, pois o valor padrão é True
. Para obter mais informações, consulte Flattening Objects (EntityDataSource).
Execute a página e você verá uma lista de alunos e funcionários (você filtrará apenas os alunos no próximo tutorial). O nome e o sobrenome são exibidos juntos.
Para classificar a exibição, clique em um nome de coluna.
Clique em Editar em qualquer linha. Caixas de texto são exibidas onde você pode alterar o nome e o sobrenome.
O botão Excluir também funciona. Clique em excluir para uma linha que tenha uma data de registro e a linha desapareça. (Linhas sem uma data de registro representam instrutores e você pode receber um erro de integridade referencial. No próximo tutorial, você filtrará essa lista para incluir apenas alunos.)
Exibindo dados de uma propriedade de navegação
Agora, suponha que você queira saber quantos cursos cada aluno está matriculado. O Entity Framework fornece essas informações na StudentGrades
propriedade de navegação da Person
entidade. Como o design do banco de dados não permite que um aluno seja matriculado em um curso sem ter uma nota atribuída, para este tutorial, você pode assumir que ter uma linha na linha da StudentGrade
tabela associada a um curso é o mesmo que estar matriculado no curso. (A Courses
propriedade de navegação é apenas para instrutores.)
Quando você usa o ContextTypeName
atributo do EntityDataSource
controle, o Entity Framework recupera automaticamente as informações de uma propriedade de navegação quando você acessa essa propriedade. Isso é chamado de carregamento lento. No entanto, isso pode ser ineficiente, pois resulta em uma chamada separada para o banco de dados sempre que informações adicionais forem necessárias. Se você precisar de dados da propriedade de navegação para cada entidade retornada pelo EntityDataSource
controle, será mais eficiente recuperar os dados relacionados junto com a própria entidade em uma única chamada para o banco de dados. Isso é chamado de carregamento ansioso e você especifica o carregamento ansioso para uma propriedade de navegação definindo a Include
propriedade do EntityDataSource
controle.
Em Students.aspx, você deseja mostrar o número de cursos para cada aluno, portanto, carregar ansiosamente é a melhor opção. Se você estivesse exibindo todos os alunos, mas mostrando o número de cursos apenas para alguns deles (o que exigiria escrever algum código além da marcação), o carregamento lento poderia ser uma escolha melhor.
Abra ou alterne para Students.aspx, alterne para o modo design , selecione StudentsEntityDataSource
e, na janela Propriedades , defina a propriedade Include como StudentGrades. (Se você quisesse obter várias propriedades de navegação, poderia especificar seus nomes separados por vírgulas — por exemplo, StudentGrades, Courses.)
Alterne para Exibição de origem. StudentsGridView
No controle , após o último asp:TemplateField
elemento, adicione o seguinte novo campo de modelo:
<asp:TemplateField HeaderText="Number of Courses">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval("StudentGrades.Count") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
Eval
Na expressão , você pode referenciar a propriedade StudentGrades
de navegação . Como essa propriedade contém uma coleção, ela tem uma Count
propriedade que você pode usar para exibir o número de cursos nos quais o aluno está registrado. Em um tutorial posterior, você verá como exibir dados de propriedades de navegação que contêm entidades individuais em vez de coleções. (Observe que você não pode usar BoundField
elementos para exibir dados de propriedades de navegação.)
Execute a página e agora você verá quantos cursos cada aluno está inscrito.
Usando um controle DetailsView para inserir entidades
A próxima etapa é criar uma página que tenha um DetailsView
controle que permitirá que você adicione novos alunos. Feche o navegador e crie uma nova página da Web usando a página master Site.Master. Nomeie a página StudentsAdd.aspx e alterne para Exibição de origem.
Adicione a marcação a seguir para substituir a marcação existente para o Content
controle chamado Content2
:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Add New Students</h2>
<asp:EntityDataSource ID="StudentsEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EnableInsert="True" EntitySetName="People">
</asp:EntityDataSource>
<asp:DetailsView ID="StudentsDetailsView" runat="server"
DataSourceID="StudentsEntityDataSource" AutoGenerateRows="False"
DefaultMode="Insert">
<Fields>
<asp:BoundField DataField="FirstMidName" HeaderText="First Name"
SortExpression="FirstMidName" />
<asp:BoundField DataField="LastName" HeaderText="Last Name"
SortExpression="LastName" />
<asp:BoundField DataField="EnrollmentDate" HeaderText="Enrollment Date"
SortExpression="EnrollmentDate" />
<asp:CommandField ShowInsertButton="True" />
</Fields>
</asp:DetailsView>
</asp:Content>
Essa marcação cria um EntityDataSource
controle semelhante ao que você criou em Students.aspx, exceto por habilitar a inserção. Assim como acontece com o GridView
controle, os campos associados do DetailsView
controle são codificados exatamente como seriam para um controle de dados que se conecta diretamente a um banco de dados, exceto que eles fazem referência às propriedades da entidade. Nesse caso, o DetailsView
controle é usado apenas para inserir linhas, portanto, você definiu o modo padrão como Insert
.
Execute a página e adicione um novo aluno.
Nada acontecerá depois de inserir um novo aluno, mas se você executar o Students.aspx, verá as novas informações do aluno.
Exibindo dados em uma lista de Drop-Down
Nas etapas a seguir, você associará um DropDownList
controle a um conjunto de entidades usando um EntityDataSource
controle . Nesta parte do tutorial, você não fará muito com essa lista. Nas partes subsequentes, porém, você usará a lista para permitir que os usuários selecionem um departamento para exibir cursos associados ao departamento.
Crie uma nova página da Web chamada Courses.aspx. No modo de exibição Origem , adicione um título ao Content
controle chamado Content2
:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Courses by Department</h2>
</asp:Content>
No modo design , adicione um EntityDataSource
controle à página como você fez antes, exceto pelo nome desta DepartmentsEntityDataSource
vez. Selecione Departamentos como o valor EntitySetName e selecione apenas as propriedades DepartmentID e Name .
Na guia Padrão da Caixa de Ferramentas, arraste um DropDownList
controle para a página, nomeie-o DepartmentsDropDownList
, clique na marca inteligente e selecione Escolher Fonte de Dados para iniciar o Assistente de Configuração do DataSource.
Na etapa Escolher uma Fonte de Dados , selecione DepartmentsEntityDataSource como a fonte de dados, clique em Atualizar Esquema e, em seguida, selecione Nome como o campo de dados a ser exibido e DepartmentID como o campo de dados de valor. Clique em OK.
O método usado para associar o controle usando o Entity Framework é o mesmo que com outros controles de fonte de dados ASP.NET, exceto que você está especificando entidades e propriedades de entidade.
Alterne para Exibição de origem e adicione "Selecionar um departamento:" imediatamente antes do DropDownList
controle.
Select a department:
<asp:DropDownList ID="DropDownList1" runat="server"
DataSourceID="EntityDataSource1" DataTextField="Name"
DataValueField="DepartmentID">
</asp:DropDownList>
Como lembrete, altere a marcação do EntityDataSource
controle neste momento substituindo os ConnectionString
atributos e DefaultContainerName
por um ContextTypeName="ContosoUniversity.DAL.SchoolEntities"
atributo . Geralmente, é melhor aguardar até que você tenha criado o controle associado a dados vinculado ao controle da fonte de dados antes de alterar a EntityDataSource
marcação de controle, pois depois que você fizer a alteração, o designer não fornecerá uma opção Atualizar Esquema no controle associado a dados.
Execute a página e você pode selecionar um departamento na lista suspensa.
Isso conclui a introdução ao uso do EntityDataSource
controle . Trabalhar com esse controle geralmente não é diferente de trabalhar com outros controles de fonte de dados ASP.NET, exceto que você faz referência a entidades e propriedades em vez de tabelas e colunas. A única exceção é quando você deseja acessar as propriedades de navegação. No próximo tutorial, você verá que a sintaxe usada com EntityDataSource
o controle também pode ser diferente de outros controles de fonte de dados ao filtrar, agrupar e ordenar dados.