Entity Framework - Relacionamentos

Em bancos de dados relacionais, relacionamento é uma situação que existe entre tabelas de bancos de dados relacionais por meio de chaves estrangeiras. Uma chave estrangeira (FK) é uma coluna ou combinação de colunas que é usada para estabelecer e impor um link entre os dados em duas tabelas. O diagrama a seguir contém três tabelas.

  • Student
  • Course
  • Enrollment

No diagrama acima, você pode ver algum tipo de associação / relacionamento entre as tabelas. Existem três tipos de relacionamento entre tabelas e o relacionamento entre diferentes tabelas depende de como as colunas relacionadas são definidas.

  • Relacionamento Um para Muitos
  • Relacionamento muitos para muitos
  • Relacionamento Um para Um

Relacionamento Um para Muitos

  • Um relacionamento um-para-muitos é o tipo mais comum de relacionamento.

  • Nesse tipo de relacionamento, uma linha na tabela A pode ter muitas linhas correspondentes na tabela B, mas uma linha na tabela B pode ter apenas uma linha correspondente na tabela A.

  • A chave estrangeira é definida na tabela que representa a extremidade múltipla do relacionamento.

  • Por exemplo, no diagrama acima, as tabelas Aluno e Matrícula têm uma relação de um para muitos, cada aluno pode ter muitas matrículas, mas cada inscrição pertence a apenas um aluno.

Na estrutura da entidade, esses relacionamentos também podem ser criados com código. A seguir está um exemplo de classes de Aluno e de Inscrição que estão associadas a um relacionamento um para muitos.

public class Student {
   public int ID { get; set; }
   public string LastName { get; set; }
   public string FirstMidName { get; set; }
   public DateTime EnrollmentDate { get; set; }
	
   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

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

No código acima, você pode ver que a classe Student contém a coleção de Enrollment, mas a classe Enrollment tem um único objeto Student.

Relacionamento muitos para muitos

No relacionamento muitos para muitos, uma linha na tabela A pode ter muitas linhas correspondentes na tabela B e vice-versa.

  • Você pode criar tal relacionamento definindo uma terceira tabela, chamada de tabela de junção, cuja chave primária consiste nas chaves estrangeiras da tabela A e da tabela B.

  • Por exemplo, as tabelas Aluno e Curso têm relacionamento de muitos para muitos que é definido pelo relacionamento de um para muitos de cada uma dessas tabelas para a tabela de inscrição.

O código a seguir contém a classe do curso e as duas classes acima, ou seja, Student e Enrollment.

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

Você pode ver que tanto a classe Curso quanto a classe Aluno têm coleções de objetos Enrollment, o que faz a relação muitos para muitos por meio da classe de junção Enrollment.

Relacionamento Um para Um

  • Em um relacionamento um-para-um, uma linha da tabela A não pode ter mais de uma linha correspondente na tabela B e vice-versa.

  • Um relacionamento um para um será criado se ambas as colunas relacionadas forem chaves primárias ou tiverem restrições exclusivas.

  • Em um relacionamento um-para-um, a chave primária atua adicionalmente como uma chave estrangeira e não há coluna de chave estrangeira separada para nenhuma das tabelas.

Esse tipo de relacionamento não é comum porque a maioria das informações relacionadas dessa forma estariam todas em uma tabela. Você pode usar um relacionamento um-para-um para -

  • Divida uma tabela com várias colunas.
  • Isole parte de uma mesa por motivos de segurança.
  • Armazene dados de curta duração e que possam ser facilmente excluídos simplesmente excluindo a tabela.
  • Armazene informações que se aplicam apenas a um subconjunto da tabela principal.

O código a seguir é para adicionar outro nome de classe StudentProfile que contém o ID de e-mail e a senha do aluno.

public class Student {
   public int ID { get; set; }
   public string LastName { get; set; }
   public string FirstMidName { get; set; }
   public DateTime EnrollmentDate { get; set; }
	
   public virtual ICollection<Enrollment> Enrollments { get; set; }
   public virtual StudentProfile StudentProfile { get; set; }
}

public class StudentProfile {

   public StudentProfile() {}
   public int ID { get; set; }
   public string Email { get; set; }
   public string Password { get; set; }
	
   public virtual Student Student { get; set; }
}

Você pode ver que a classe de entidade Student contém a propriedade de navegação StudentProfile e a propriedade StudentProfile contém a propriedade de navegação Student.

Cada aluno possui apenas um e-mail e senha para fazer o login no domínio universitário. Essas informações podem ser adicionadas à tabela do Aluno, mas por motivos de segurança, são separadas em outra tabela.