Compartilhar via


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

Captura de tela da janela Explorer da Internet, que mostra o modo de exibição Lista de Alunos com uma lista de nomes, datas de inscrição e cursos dos alunos.

Captura de tela da janela Explorer da Internet, mostrando a exibição Adicionar Novos Alunos com o nome de John Smith e a data de inscrição preenchidas nos campos de texto.

Captura de tela da janela Explorer da Internet, que mostra a exibição Cursos por Departamento com um menu suspenso para departamentos.

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.

Imagem23

Especifique Site.Master como a página master. Todas as páginas criadas para esses tutoriais usarão esta página master.

Imagem24

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 .

Imagem01

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.

Imagem02

Observação: se você receber a caixa de diálogo a seguir neste ponto, precisará compilar o projeto antes de continuar.

Imagem25

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.

Imagem03

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, StudentGradee 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.

Imagem04

Na janela Propriedades , expanda ESPECIFICAÇÃO INSERT e UPDATE e defina a propriedade DeleteRule como Cascade.

Imagem05

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 StudentGradee selecione Propriedades.

Imagem21

Na janela Propriedades , defina End1 OnDelete como Cascade.

Imagem22

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 EntityDataSourceStudentsGridView, clique na marca inteligente e selecione StudentsEntityDataSource como a fonte de dados.

Image06

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.

Imagem10

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

Imagem11

Selecione o campo FirstMidName e clique em Converter este campo em um TemplateField.

Faça o mesmo para EnrollmentDate.

Imagem13

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 os ConnectionString atributos e DefaultContainerName , ele executa trabalho adicional para carregar metadados em cada solicitação. Isso não será necessário se você especificar o ContextTypeName 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 o EntityDataSource 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.

Imagem07

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.

Imagem08

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

Imagem19

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

Captura de tela da janela Explorer da Internet, mostrando a exibição Adicionar Novos Alunos com o nome de John Smith e a data de inscrição preenchidas nos campos de texto.

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.

Captura de tela da janela Explorer da Internet, mostrando a exibição Adicionar Novos Alunos com o nome de John Smith e a data de inscrição preenchidas nos campos de texto.

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 DepartmentsEntityDataSourcevez. Selecione Departamentos como o valor EntitySetName e selecione apenas as propriedades DepartmentID e Name .

Imagem15

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.

Imagem16

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.

Imagem17

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.

Captura de tela da janela do navegador Explorer internet, que mostra a exibição Cursos por Departamento com um menu suspenso para departamentos.

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.