我正在进行一个使用实体框架6.1.3的项目。现在,当向父实体的列表中添加子对象时,我们遇到了相当大的性能问题(参见下面的代码示例)。
我们使用的是延迟加载,所以我注意到,在调用_parent.Children.Add(child);之前,一切都很好,因为它似乎只是为了添加一个新的数据库而从数据库加载所有的子程序。因为我们的一些父对象有大约5万个子对象,这使得这个简单的插入调用延迟了7-8秒,有时甚至导致超时。
对我来说,实体框架只是为了添加一个子程序而加载所有的子元素是没有意义的,所以有什么方法可以避免这种情况吗?或者这是实体框架的设计缺陷,我们应该找到一个解决办法吗?
显然,我希望找到解决这个问题的方法,并且不希望为这个问题实现纯ADO查询。
谢谢!
public class Parent
{
public Guid Id { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
public class Child
{
public Guid Id { get; set; }
}
public class ParentAggregate
{
private readonly Parent _state;
public ParentAggregate(Parent state)
{
_state = state;
}
public void AddChild(Guid id)
{
var child = new Child { Id = id };
_state.Children.Add(child);
}
}发布于 2018-12-19 15:20:20
对我来说,实体框架只是为了添加一个子程序而加载所有的子程序是没有意义的
延迟加载发生在您第一次通过getter访问导航属性时。以及示例代码
_parent.Children.Add(child);包括两项行动:
(1)检索Children属性(通过属性getter!):
var children = _parent.Children;(2)对其执行一些操作(在本例中调用Add方法):
children.Add(child);延迟加载是因为操作(1)。正如你所看到的,EF与此无关,因为它无法控制它。并且无法知道您将如何处理该属性值--枚举它、进行计数或使用Add、Remove等方法。
以下是一些解决办法。
首先,为什么要使用延迟加载?它有许多副作用和低效,所有这些都可以很容易地解决通过EF提供的箱外急切加载通过Include方法。这就是为什么默认情况下future (“EF的未来”)在默认情况下不使用延迟加载,并且需要一个特殊的包和过程来启用它。
其次,如果坚持使用延迟加载,则有以下两个选项:
(A)在数据修改期间禁用延迟加载(需要访问/控制DbContext实例):
dbContext.Configuration.LazyLoadingEnabled = false;
_parent.Children.Add(child);
dbContext.Configuration.LazyLoadingEnabled = true;这还需要初始化集合属性以避免NRE。
(B)使用显式支持字段并提供对其的一些直接访问(以避免属性访问器触发延迟加载)。例如:
public class Parent
{
public Guid Id { get; set; }
private ICollection<Child> children;
public virtual ICollection<Child> Children { get => children; set => children = value; }
public void Add(Child child)
{
// use the backing field directly
if (children == null) children = new HashSet<Child>();
children.Add(child);
}
}https://stackoverflow.com/questions/53853111
复制相似问题