我有一个课程:
[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
及其相关的Users
或TimeEntries
。
所以,返回所有程序的json及其相关活动。我用了Include
:
//...
var programActivities = db.Programs.Include(p => p.Activities);
正如预期的那样,json发出了程序和嵌套活动。好。
但是,它还会返回每个Program's
相关联的TimeEntries
和Users
。没想到!我读过的其他文章表明您使用一个。Include
来返回每个相关对象,因此如果您不使用.include作为对象,那么不明白。
我是否需要使用额外的开关或选项来排除其他相关对象?
答案 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; }
这将允许您保持延迟加载,同时防止加载其余属性。这一切都取决于您的应用程序设计,例如,如果您需要使用延迟加载或者您的导航属性需要偶尔暴露。