好吧,所以我有两个模型老师和帐户:
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的新外键。如何在教师和帐户中保留导航映射(虚拟对象)的同时解决此问题。
答案 0 :(得分:2)
映射一对一关系的正确方法是:
从AccountID
删除Teacher
属性。 Teacher
是您关系中的主体,因此它不能拥有依赖Account
的外键。
从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
和Account
表格中有以下行...
...您可以运行此查询...
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以获得更详尽的解释