【问题标题】:EF Code First object graph memory use in WPF appWPF 应用程序中的 EF Code First 对象图内存使用
【发布时间】:2012-10-27 22:40:03
【问题描述】:

我正在构建一个应用程序来显示来自源代码控制存储库的更改历史日志。该应用在 .NET 4 WPF 和 Entity Framework Code First 中实现。

我遇到的一个问题是,随着时间的推移,随着更多日志条目被添加到日志中,应用程序会使用越来越多的内存并且不会释放对日志条目的引用。每个日志条目都包含一个“已更改文件”列表,并且对于每个已更改文件,文件的前后版本。

UI 显示日志条目列表以及当前选定的LogEntryChangedFile 的新旧版本之间的差异。数据模型大致如下:

public class LogSubscription
{
    public List<LogEntry> Log { get; set; }
}

public class LogEntry
{
    public List<ChangedFile> ChangedFiles { get; set; }
}

public class ChangedFile
{
    public string OldVersion { get; set; }
    public string NewVersion { get; set; }
}

由于我使用的是 EF Code First,因此只需访问 List 属性即可查询数据库并自动构建对象模型。我想做的是在一段时间后以某种方式取消引用ChangedFiles 列表,并根据需要重新查询数据库并重建对象模型(即用户已单击返回日志条目)。

EF Code First 有什么方法可以做到这一点?或者我应该采取不同的方法来控制所使用的内存?

应用程序和完整源代码托管在 GitHub 上:https://github.com/tomhunter-gh/SourceLog

【问题讨论】:

  • 如果您为应用程序使用单个上下文实例,它将保存对已加载实体的所有引用,直到您手动分离它们或释放上下文实例。
  • 谢谢@LadislavMrnka。基本上是在处理上下文时不能使用延迟加载的情况吗?我认为这是我感到困惑的地方,也是我之前遇到问题的地方..

标签: c# wpf memory-management entity-framework-4.1 ef-code-first


【解决方案1】:

正如评论中所说:这很可能发生在从未处理过的静态上下文中。我在源代码中看到有一个ThreadStaticContextBackgroundLogEntry 使用:在类似活动记录的模式中,LogEntry 通过其MarkAsReadAndSave 方法保存自己,为此它需要一个上下文。

您可能这样做(我并没有仔细检查源代码)以防止在保存日志条目时创建和处置许多上下文。但我认为你应该重新考虑主动记录方法。日志条目由MainWindowViewModel 保存。视图模型应该调用一个服务方法,该方法通过一个短暂的上下文保存日志条目,并可能缓存这些条目以使其可用于显示等。它应该从DgLogSelectionChanged接收RemovedItems集合以便处理它们通过一个上下文而不是每个项目一个上下文。这有意义吗?

【讨论】:

  • 感谢@Gert 的反馈。我想问题是我可以在没有静态上下文引用的情况下进行延迟加载吗?如果我没有静态引用,我将如何进行 ChangeFiles 集合的延迟加载和卸载?任何文章链接将不胜感激 - 我在卸载问题上找不到太多..谢谢
  • 不,你不能在没有上下文的情况下进行延迟加载,但也许你应该拥有在需要时提供数据的服务方法,而不是依赖对象的导航属性。因此,卸载会更容易:只需清空或处置集合变量。
  • 是的,这是有道理的。快速提问 - 如果我清空集合属性然后保存父实体,这会删除集合中的实体吗?您可以指出这种行为的任何例子吗?谢谢
  • 如果您加载一个集合然后清除它,是的,EF 会将此视为删除实体或至少破坏与父对象的关联的请求。参见例如this question.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多