65.9K
CodeProject 正在变化。 阅读更多。
Home

Entity Framework Code First 中的一对零/一对关系

2014 年 8 月 14 日

CPOL

2分钟阅读

viewsIcon

65180

downloadIcon

539

在这里,我们将了解如何在 Entity Framework Code First 中配置两个实体之间的一对零/一对关系

引言

使用 entity framework code first 很有趣。但上周,我在配置实体之间的一对零或一对关系时遇到了一些问题,尤其是在使用诸如 HasOptionalWithRequiredWithOptionalPrincipalWithOptionalDependent 等关键字的组合时。

因此,让我们看看如何使用这些关键字的组合来建立表之间的关系。以及针对不同的组合,哪些不同的结构化表被填充。

背景

假设我们有两个实体,StudentStudentContact,其中

  • Student 可能只有一个联系人 (StudentContact) 或没有
  • 但每个联系人 (StudentContact) 必须有一个 Student
public class Student
{
    public long Id { get; set; }
    public string Name { get; set; }
    /*May have a contact or not*/
    public virtual StudentContact Contact { get; set; }
}

public class StudentContact
{
    public long Id { get; set; }
    public string ContactNumber { get; set; }
    /*Must have a Student*/
    public virtual Student Student { get; set; }
}

选项 1:HasOptional 然后 WithRequired

配置关系:从 Student 配置

Student 配置

HasKey(x => x.Id);
Property(x => x.Id)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

HasOptional(x => x.Contact)
    .WithRequired(l => l.Student);

StudentContact 配置

HasKey(x => x.Id);
Property(x => x.Id)
    .HasColumnName("Student_Id")
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

Student:

  • Id 是主键,带有自动递增

StudentContact:

  • Id (Student_Id,因为我们进行了自定义) 既是主键又是来自 StudentId 列的外键

选项 2:HasOptional 然后 WithOptionalPrincipal

配置关系:从 Student 配置

Student 配置

HasKey(x => x.Id);
Property(x => x.Id)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

HasOptional(x => x.Contact)
    .WithOptionalPrincipal(l => l.Student);

StudentContact 配置

HasKey(x => x.Id);
Property(x => x.Id)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

Student:

  • Id 是主键,带有自动递增

StudentContact:

  • Id 是主键,带有自动递增
  • Student_Id 自动创建,并且在 StudentContact/Student 实体中没有导航属性
  • Student_Id 不可为 null,并且是来自 StudentId 列的外键

选项 3:HasOptional 然后 WithOptionalDependent

配置关系:从 Student 配置。

Student 配置

HasKey(x => x.Id);
Property(x => x.Id)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

HasOptional(x => x.Contact)
    .WithOptionalDependent(l => l.Student);

StudentContact 配置

HasKey(x => x.Id);
Property(x => x.Id)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

Student:

  • Id 是主键,带有自动递增
  • Contact_Id 自动创建,并且在 StudentContact/Student 实体中没有导航属性
  • Contact_Id 是来自 StudentContactId 列的可为 null 的外键

StudentContact:

  • Id 是主键,带有自动递增

好吧,一些书籍是这样描述的

选择 WithRequiredPrincipal 将使您正在配置的实体成为主要的实体,这意味着它包含关系的 primary key。

选择 WithRequiredDependent 将使您正在配置的实体成为从属实体,这意味着它将具有关系的外键。

有趣的事情!!!

到目前为止,我们已经从 Student 配置中配置了关系,但假设我们想从 Student Contact 配置中配置关系,那么我们可以做什么…!!!

选项1Mimic:HasRequired 然后 WithOptional

配置关系:从 StudentContact 配置。

StudentContact 配置

HasKey(x => x.Id);
Property(x => x.Id)
    .HasColumnName("Student_Id")
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

HasRequired(x => x.Student)
    .WithOptional(l => l.Contact);

Student 配置

HasKey(x => x.Id);
Property(x => x.Id)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

这将与 选项1 相同

选项2Mimic:HasRequired 然后 WithOptional

配置关系:从 StudentContact 配置。

StudentContact 配置

HasKey(x => x.Id);
Property(x => x.Id)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

HasRequired(x => x.Student)
    .WithOptional(l => l.Contact)
    .Map(x => x.MapKey("Student_Id"));

Student 配置

HasKey(x => x.Id);
Property(x => x.Id)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

这将与 选项2 相同。

选项3Mimic:HasRequired 然后 WithOptional

无法从 StudentContact 配置中配置关系。

限制

  1. 是的,可能存在一些我尚未遇到的错误,或者可能造成一些道德干扰。所以,如果您发现任何错误,请告诉我。
  2. 还有一些问题,例如我避免使用的导航属性。

在附件中查找框架 4 项目的 Visual Studio 2010(可在 VS2013 中运行)解决方案。如果运行该项目,它将在本地计算机上创建一个具有 2 个表和数据的 "UMS" 数据库。您可以使用 app.config 进行更改。

© . All rights reserved.