实体框架'包括'包括超过它应该

时间:2015-05-14 11:19:22

标签: c# entity-framework eager-loading

我有一个课程:

[Table("Program")]
public class Program
{
    [Key]
    public long ProgramId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public bool IsActive { get; set; }
    public virtual ICollection<Activity> Activities { get; set; }
    public virtual ICollection<User> Users { get; set; }
    public virtual ICollection<TimeEntry> TimeEntries { get; set; }
 }

典型的使用模式是抓取Program及其所有关联的Activities。更少需要Programs及其相关的UsersTimeEntries

所以,返回所有程序的json及其相关活动。我用了Include

//...
var programActivities = db.Programs.Include(p => p.Activities);

正如预期的那样,json发出了程序和嵌套活动。好。

但是,它还会返回每个Program's相关联的TimeEntriesUsers。没想到!我读过的其他文章表明您使用一个。Include来返回每个相关对象,因此如果您不使用.include作为对象,那么不明白。

我是否需要使用额外的开关或选项来排除其他相关对象?

2 个答案:

答案 0 :(得分:2)

请勿将导航属性声明为virtual或禁用延迟加载行为。默认情况下启用延迟加载,通过创建派生代理类型的实例,然后覆盖virtual属性以添加加载挂钩来实现。所以,如果你想使用JSON,我建议你关闭延迟加载:

public class YourContext : DbContext 
{ 
    public YourContext() 
    { 
        this.Configuration.LazyLoadingEnabled = false; 
    } 
}

现在,您可以使用Include扩展方法作为查询的一部分加载所需的相关实体。此行为称为预先加载

这些链接可以帮助您更好地理解我在答案中解释的内容:

答案 1 :(得分:0)

在Entity Framework中,当使用像db.Programs.Include(p => p.Activities)这样的Include语句时,基本上确保将急切加载导航属性,而不是延迟加载。从本质上讲,这意味着使用一个数据库查询来获取Program及其相关Activites而不是两个的数据。

问题是,如果为上下文启用了延迟加载,那么获取其余导航属性的任何尝试都将导致额外的数据库调用。这可能是JSON序列化程序尝试序列化Program对象时发生的情况。

为了防止这种情况,您应该寻找一种方法来排除导航属性的序列化,因此永远不会从数据库中加载它们。例如:

[JsonIgnore]
public virtual ICollection<User> Users { get; set; }

[JsonIgnore]
public virtual ICollection<TimeEntry> TimeEntries { get; set; }

这将允许您保持延迟加载,同时防止加载其余属性。这一切都取决于您的应用程序设计,例如,如果您需要使用延迟加载或者您的导航属性需要偶尔暴露。