上下文没有拉入一个对象

时间:2012-09-16 16:09:31

标签: c# .net entity-framework ef-code-first

好吧,所以我有两个模型老师和帐户:

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

这是对的吗?

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

更新

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

2 个答案:

答案 0 :(得分:2)

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

  • AccountID删除Teacher属性。 Teacher是您关系中的主体,因此它不能拥有依赖Account的外键。

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

    < / LI>

那么,你会有:

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

如果您现在TeacherAccount表格中有以下行...

One-to-One data

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

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

...由于成功延迟加载accountName导航属性,"Account 1"将具有值teacher.Account

答案 1 :(得分:0)

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

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

剩下的就是使用Eager加载:

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

查看here以获得更详尽的解释