Introdução com o Entity Framework 4.0 Database First e o ASP.NET 4 Web Forms – Parte 6
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
Implementando herança de tabela por hierarquia
No tutorial anterior, você trabalhou com dados relacionados adicionando e excluindo relações e adicionando uma nova entidade que tinha uma relação com uma entidade existente. Este tutorial mostrará como implementar a herança no modelo de dados.
Na programação orientada a objetos, você pode usar a herança para facilitar o trabalho com classes relacionadas. Por exemplo, você pode criar Instructor
classes e Student
que derivam de uma Person
classe base. Você pode criar os mesmos tipos de estruturas de herança entre entidades no Entity Framework.
Nesta parte do tutorial, você não criará novas páginas da Web. Em vez disso, você adicionará entidades derivadas ao modelo de dados e modificará as páginas existentes para usar as novas entidades.
Herança de tabela por hierarquia versus tabela por tipo
Um banco de dados pode armazenar informações sobre objetos relacionados em uma tabela ou em várias tabelas. Por exemplo, no School
banco de dados, a Person
tabela inclui informações sobre alunos e instrutores em uma única tabela. Algumas das colunas se aplicam somente a instrutores (HireDate
), algumas somente aos alunos (EnrollmentDate
) e outras a ambos (LastName
, FirstName
).
Você pode configurar o Entity Framework para criar Instructor
entidades e Student
herdadas da Person
entidade. Esse padrão de geração de uma estrutura de herança de entidade de uma única tabela de banco de dados é chamado de herança de tabela por hierarquia (TPH).
Para cursos, o School
banco de dados usa um padrão diferente. Cursos online e cursos no local são armazenados em tabelas separadas, cada uma com uma chave estrangeira que aponta para a Course
tabela. As informações comuns a ambos os tipos de curso são armazenadas apenas na Course
tabela.
Você pode configurar o modelo de dados do Entity Framework para que OnlineCourse
as entidades e OnsiteCourse
herdem da Course
entidade. Esse padrão de geração de uma estrutura de herança de entidade de tabelas separadas para cada tipo, com cada tabela separada fazendo referência a uma tabela que armazena dados comuns a todos os tipos, é chamado de herança de tabela por tipo (TPT).
Os padrões de herança de TPH geralmente oferecem melhor desempenho no Entity Framework do que os padrões de herança TPT, pois os padrões TPT podem resultar em consultas de junção complexas. Este passo a passo demonstra como implementar a herança de TPH. Você fará isso executando as seguintes etapas:
- Criar
Instructor
eStudent
tipos de entidade que derivam dePerson
. - Mova as propriedades que pertencem às entidades derivadas da
Person
entidade para as entidades derivadas. - Defina restrições em propriedades nos tipos derivados.
- Torne a
Person
entidade uma entidade abstrata. - Mapeie cada entidade derivada para a
Person
tabela com uma condição que especifica como determinar se umaPerson
linha representa esse tipo derivado.
Adicionando entidades de instrutor e aluno
Abra o arquivo SchoolModel.edmx , clique com o botão direito do mouse em uma área desocupada no designer, selecione Adicionar e, em seguida, selecione Entidade.
Na caixa de diálogo Adicionar Entidade , nomeie a entidade Instructor
e defina sua opção Tipo base como Person
.
Clique em OK. O designer cria uma Instructor
entidade derivada da Person
entidade . A nova entidade ainda não tem nenhuma propriedade.
Repita o procedimento para criar uma Student
entidade que também deriva de Person
.
Somente instrutores têm datas de contratação, portanto, você precisa mover essa propriedade da Person
entidade para a Instructor
entidade. Na entidade , clique com o Person
botão direito do mouse na HireDate
propriedade e clique em Recortar. Em seguida, clique com o botão direito do mouse em Propriedades na Instructor
entidade e clique em Colar.
A data de contratação de uma Instructor
entidade não pode ser nula. Clique com o botão direito do mouse na HireDate
propriedade, clique em Propriedades e, na janela Propriedades , altere Nullable
para False
.
Repita o procedimento para mover a EnrollmentDate
propriedade da Person
entidade para a Student
entidade. Verifique se você também definiu Nullable
como False
para a EnrollmentDate
propriedade .
Agora que uma Person
entidade tem apenas as propriedades comuns às Instructor
entidades e Student
(além das propriedades de navegação, que você não está movendo), a entidade só pode ser usada como uma entidade base na estrutura de herança. Portanto, você precisa garantir que ela nunca seja tratada como uma entidade independente. Clique com o botão direito do mouse na Person
entidade, selecione Propriedades e, na janela Propriedades , altere o valor da propriedade Abstract para True.
Mapeando entidades de instrutor e aluno para a tabela Person
Agora você precisa informar ao Entity Framework como diferenciar entre Instructor
as entidades e Student
no banco de dados.
Clique com o botão direito do mouse na Instructor
entidade e selecione Mapeamento de Tabela. Na janela Detalhes do Mapeamento , clique em Adicionar uma Tabela ou Exibição e selecione Pessoa.
Clique em Adicionar uma Condição e selecione HireDate.
Altere Operator para Is e Value/Property para Not Null.
Repita o procedimento para a Students
entidade, especificando que essa entidade é mapeada para a Person
tabela quando a EnrollmentDate
coluna não é nula. Em seguida, salve e feche o modelo de dados.
Compile o projeto para criar as novas entidades como classes e disponibilizá-las no designer.
Usando as entidades de instrutor e aluno
Quando você criou as páginas da Web que trabalham com dados de alunos e instrutores, você as Person
vincula ao conjunto de entidades e filtra na HireDate
propriedade ou EnrollmentDate
para restringir os dados retornados aos alunos ou instrutores. No entanto, agora, quando você associa cada controle de fonte de dados ao Person
conjunto de entidades, pode especificar que somente Student
os tipos de entidade ou Instructor
devem ser selecionados. Como o Entity Framework sabe como diferenciar alunos e instrutores no Person
conjunto de entidades, você pode remover as Where
configurações de propriedade inseridas manualmente para fazer isso.
No Visual Studio Designer, você pode especificar o tipo de entidade que um EntityDataSource
controle deve selecionar na caixa suspensa EntityTypeFilter do Configure Data Source
assistente, conforme mostrado no exemplo a seguir.
E, na janela Propriedades , você pode remover Where
valores de cláusula que não são mais necessários, conforme mostrado no exemplo a seguir.
No entanto, como você alterou a marcação de controles para EntityDataSource
usar o ContextTypeName
atributo , não é possível executar o assistente Configurar Fonte de Dados em EntityDataSource
controles que você já criou. Portanto, você fará as alterações necessárias alterando a marcação.
Abra a página Students.aspx . StudentsEntityDataSource
No controle , remova o Where
atributo e adicione um EntityTypeFilter="Student"
atributo . A marcação agora será semelhante ao seguinte exemplo:
<asp:EntityDataSource ID="StudentsEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EntitySetName="People" EntityTypeFilter="Student"
Include="StudentGrades"
EnableDelete="True" EnableUpdate="True"
OrderBy="it.LastName" >
</asp:EntityDataSource>
Definir o EntityTypeFilter
atributo garante que o EntityDataSource
controle selecione apenas o tipo de entidade especificado. Se você quisesse recuperar os Student
tipos de entidade e Instructor
, não definiria esse atributo. (Você tem a opção de recuperar vários tipos de entidade com um EntityDataSource
controle somente se estiver usando o controle para acesso a dados somente leitura. Se você estiver usando um EntityDataSource
controle para inserir, atualizar ou excluir entidades e se o conjunto de entidades ao qual ele está associado puder conter vários tipos, você só poderá trabalhar com um tipo de entidade e terá que definir esse atributo.)
Repita o procedimento para o SearchEntityDataSource
controle, exceto remover apenas a parte do Where
atributo que seleciona entidades Student
em vez de remover a propriedade completamente. A marca de abertura do controle agora será semelhante ao seguinte exemplo:
<asp:EntityDataSource ID="SearchEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EntitySetName="People" EntityTypeFilter="Student"
Where="it.FirstMidName Like '%' + @StudentName + '%' or it.LastName Like '%' + @StudentName + '%'" >
Execute a página para verificar se ela ainda funciona como antes.
Atualize as seguintes páginas que você criou em tutoriais anteriores para que elas usem as entidades e Instructor
novas Student
em vez de Person
entidades e, em seguida, execute-as para verificar se elas funcionam como antes:
Em StudentsAdd.aspx, adicione
EntityTypeFilter="Student"
aoStudentsEntityDataSource
controle . A marcação agora será semelhante ao seguinte exemplo:<asp:EntityDataSource ID="StudentsEntityDataSource" runat="server" ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" EntitySetName="People" EntityTypeFilter="Student" EnableInsert="True" </asp:EntityDataSource>
Em About.aspx, adicione
EntityTypeFilter="Student"
aoStudentStatisticsEntityDataSource
controle e removaWhere="it.EnrollmentDate is not null"
. A marcação agora será semelhante ao seguinte exemplo:<asp:EntityDataSource ID="StudentStatisticsEntityDataSource" runat="server" ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" EntitySetName="People" EntityTypeFilter="Student" Select="it.EnrollmentDate, Count(it.EnrollmentDate) AS NumberOfStudents" OrderBy="it.EnrollmentDate" GroupBy="it.EnrollmentDate" > </asp:EntityDataSource>
Em Instructors.aspx e InstructorsCourses.aspx, adicione
EntityTypeFilter="Instructor"
aoInstructorsEntityDataSource
controle e removaWhere="it.HireDate is not null"
. A marcação em Instructors.aspx agora se assemelha ao seguinte exemplo:<asp:EntityDataSource ID="InstructorsEntityDataSource" runat="server" ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="false" EntitySetName="People" EntityTypeFilter="Instructor" Include="OfficeAssignment" EnableUpdate="True"> </asp:EntityDataSource>
A marcação em InstructorsCourses.aspx agora será semelhante ao seguinte exemplo:
<asp:EntityDataSource ID="InstructorsEntityDataSource" runat="server" ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" EntitySetName="People" EntityTypeFilter="Instructor" Select="it.LastName + ',' + it.FirstMidName AS Name, it.PersonID"> </asp:EntityDataSource>
Como resultado dessas alterações, você melhorou a manutenção do aplicativo da Contoso University de várias maneiras. Você moveu a lógica de seleção e validação para fora da camada de interface do usuário (marcação.aspx ) e a tornou parte integrante da camada de acesso a dados. Isso ajuda a isolar o código do aplicativo de alterações que você pode fazer no futuro para o esquema de banco de dados ou o modelo de dados. Por exemplo, você pode decidir que os alunos podem ser contratados como auxiliares dos professores e, portanto, obteriam uma data de contratação. Em seguida, você pode adicionar uma nova propriedade para diferenciar os alunos dos instrutores e atualizar o modelo de dados. Nenhum código no aplicativo Web precisaria ser alterado, exceto onde você queria mostrar uma data de contratação para os alunos. Outro benefício da adição Instructor
e Student
das entidades é que seu código é mais facilmente compreensível do que quando se refere a Person
objetos que eram, na verdade, alunos ou instrutores.
Agora você viu uma maneira de implementar um padrão de herança no Entity Framework. No tutorial a seguir, você aprenderá a usar procedimentos armazenados para ter mais controle sobre como o Entity Framework acessa o banco de dados.