1

好的,所以我有两个模型教师和帐户:

public class Teacher : Person
{
    [Key]
    public Guid TeacherID { get; set; }

    public Guid? AccountID { get; set; }

    [Display(Name = "Hire Date")]
    [DataType(DataType.Date)]
    public DateTime? HireDate { get; set; }

    public virtual ICollection<Classroom> Classrooms { get; set; }

    public virtual Office Office { get; set; }

    public virtual Account Account { get; set; }
}

public class Account
{
    [Key]
    public Guid AccountID { get; set; }

    public Guid? TeacherID { get; set; }

    public String Username { get; set; }

    public String Salt { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public String SaltedPassword { get; set; }

    [Display(Name = "Secert Question")]
    public Guid SecertQuestionID { get; set; }

    [Display(Name = "Answer")]
    public String SecertAnswer { get; set; }

    public Guid RoleID { get; set; }

    public virtual SecertQuestion Question { get; set; }

    public virtual Role Role { get; set; }

    public virtual Teacher Teacher { get; set; }
}

当我运行 GetAll 查询时:

public IEnumerable<Account> GetAll()
{
    return context.Accounts;
}

我的教师对象返回 null 而不是像我的 Role 和 SecertQuestion 对象那样填充。

我有假数据,可确保两个表中的 TeacherID 和 AccountID 具有相同的 GUID。此外,在我的上下文创建中,我正在使用此代码创建一个可选关系:

modelBuilder.Entity<Account>()
    .HasOptional(a => a.Teacher)
    .WithOptionalDependent(a => a.Account);

它是否正确?

所以我的问题是,当我为我的对象 Account 执行 GetAll() 时,为什么我的 Teacher 对象返回 null?是因为我的帐户对象有一个可以为空的教师对象与之关联吗?

更新:

所以在分析了我的数据库之后,我注意到在我当前的映射中,我的 Account 表正在创建一个名为 Teacher_TeacherID 的新外键。我该如何解决这个问题,同时在教师和帐户中保留我的导航映射(虚拟对象)。

4

2 回答 2

2

映射一对一关系的正确方法是:

  • 从. AccountID_ 是您关系中的主体,因此它不能具有依赖于的外键。TeacherTeacherAccount

  • 从类中删除TeacherID属性Account。您不能在模型类中公开此外键。(我不知道为什么,tbh,但是 EF 按照惯例不将此属性识别为外键,并且一对一映射没有HasForeignKey可用的方法。)

所以,你会:

public class Teacher : Person
{
    [Key]
    public Guid TeacherID { get; set; }
    //...
    public string Name { get; set; }  // only for the test example below
    //...
    public virtual Account Account { get; set; }
}

public class Account
{
    [Key]
    public Guid AccountID { get; set; }
    //...
    public string Name { get; set; }  // only for the test example below
    //...
    public virtual Teacher Teacher { get; set; }
}

使用 Fluent API 映射外键:

modelBuilder.Entity<Account>()
    .HasOptional(a => a.Teacher)
    .WithOptionalDependent(a => a.Account)
    .Map(m => m.MapKey("TeacherID"));

TeacherID这将在表中创建一个可为空的外键列Account

Teacher如果您现在在andAccount表中有以下行...

一对一数据

...您可以运行此查询...

var teacher = context.Teachers.First(t => t.Name == "Teacher 1");
var accountName = teacher.Account.Name;

...并且由于导航属性的成功延迟加载而accountName具有该值。"Account 1"teacher.Account

于 2012-09-17T20:11:26.097 回答
0

默认情况下不填充导航属性。这是一件好事,因为它可以防止无意中加载大量数据。

通常延迟加载会在您第一次访问它时启动并加载教师。但是通过使用存储库模式,您将失去此功能。

剩下的就是使用 Eager 加载:

public IEnumerable<Account> GetAll() 
    { 
        return context.Accounts.Include(account=>account.Teacher); 
    } 

这里以获得更详尽的解释

于 2012-09-16T16:19:07.440 回答