我首先使用代码和实体框架。
我有一个Registration
实体,它有几个其他模型的属性:
public class Registration
{
public int ID { get; set; }
public int OrganizationID { get; set; }
public Address RegAddress { get; set; }
public ContactInformation RegContactInformation { get; set; }
public string Signature{ get; set; }
}
通过此设置,我确实拥有Address
和ContactInformation
模型。当我保存注册时,它可以像我期望的那样工作。包含3个表(Registration
,Address
和ContactInformation
)的数据库。 Registration
将FK与其他两个一起使用。
但是当我尝试使用EF从我的数据库中获取注册时:
DBConnections dbConnections = new DBConnections();
var registrations = from r in dbConnections.PlayerRegistrations
where r.OrganizationID == orgID
select r;
Registration.Address和Registration.ContactInformation
为空。我怎样才能做到这一点?
答案 0 :(得分:2)
这是正确的行为,因为EF从不加载相关实体本身。要加载相关属性,您必须使用以下方法之一:
延迟加载将为您提供相关实体的自动加载,但它会为数据库生成其他查询。首次访问该属性时,将加载相关实体或相关集合。要使用延迟加载,必须将实体中的所有导航属性标记为virtual
(也不能禁用延迟加载或代理创建 - 默认情况下允许)。仅当用于加载主实体的上下文仍处于活动状态时,延迟加载才有效。要允许延迟加载,您必须修改您的实体:
public class Registration
{
public int ID { get; set; }
public int OrganizationID { get; set; }
public virtual Address RegAddress { get; set; }
public virtual ContactInformation RegContactInformation { get; set; }
public string Signature{ get; set; }
}
预先加载将定义哪个关系必须与主实体一起加载。预先加载由Include
方法定义。您可以重写查找为:
var registrations = from r in dbConnections.PlayerRegistrations
.Include(p => p.Address)
.Include(p => p.RegContactInformation)
where r.OrganizationID == orgID
select r;
请注意,从数据库中返回的数据量和形式急切加载has big impact。
显式加载将允许您明确说明应该加载某些关系。您甚至可以为加载相关实体定义一些条件,这是其他两种方法无法实现的。您必须先加载主实体,然后在处理上下文之前,您可以执行以下操作:
context.Entry(registration).Reference(c => c.Address).Load();
此方法对于加载相关集合更有用。
自定义加载意味着您将对每个关系使用单独的查询。它看起来像你不想做的事情,但对于传输结果集的一些性能优化,这可能非常有用(这解决了在急切加载部分中链接的问题)。这种方法的关键在于,如果对关系使用单独的查询,EF仍将正确填充导航属性。此方法仅适用于加载相关集合,仅在延迟加载时才有效。