- 实体框架教程
- 实体框架 - 主页
- 实体框架 - 概述
- 实体框架 - 架构
- 实体 F - 环境设置
- 实体框架 - 数据库设置
- 实体框架 - 数据模型
- 实体框架-DbContext
- 实体框架 - 类型
- 实体框架 - 关系
- 实体框架 - 生命周期
- 实体 F - 代码优先方法
- 实体 F - 模型优先方法
- 实体 F - 数据库优先方法
- 实体框架 - DEV 方法
- 实体F——数据库操作
- 实体框架 - 并发
- 实体框架 - 事务
- 实体框架 - 视图
- 实体框架 - 索引
- 实体 F - 存储过程
- 实体 F - 断开连接的实体
- 实体 F - 表值函数
- 实体框架 - 本机 SQL
- 实体框架 - 枚举支持
- 实体F - 异步查询
- 实体框架 - 持久性
- 实体 F - 投影查询
- 实体 F - 命令记录
- 实体F——命令拦截
- 实体框架 - 空间数据类型
- 实体框架 - 继承
- 实体框架 - 迁移
- 实体框架 - 预加载
- 实体框架 - 延迟加载
- 实体框架 - 显式加载
- 实体框架 - 验证
- 实体框架 - 跟踪更改
- 实体框架 - 彩色实体
- 实体 F - 代码优先方法
- 实体框架 - 第一个示例
- 实体框架 - 数据注释
- 实体框架 - 流畅的 API
- 实体框架-种子数据库
- 实体 F - 代码优先迁移
- 实体 F - 多个 DbContext
- 实体 F - 嵌套实体类型
- 实体框架资源
- 实体框架 - 快速指南
- 实体框架 - 有用的资源
- 实体框架 - 讨论
实体框架 - 生命周期
寿命
上下文的生命周期从实例创建时开始,到实例被释放或垃圾回收时结束。
当我们使用 ORM 时,上下文生命周期是一个非常关键的决定。
上下文的执行方式类似于实体缓存,因此这意味着它保存对所有已加载实体的引用,这些实体的内存消耗可能会快速增长,并且还可能导致内存泄漏。
在下图中,您可以看到通过 Context 从应用程序到数据库的上层数据工作流程,反之亦然。
实体生命周期
实体生命周期描述了实体的创建、添加、修改、删除等过程。实体在其生命周期中有多种状态。在了解如何检索实体状态之前,我们先来看看什么是实体状态。状态是System.Data.EntityState类型的枚举,声明以下值 -
已添加:实体被标记为已添加。
已删除:实体被标记为已删除。
已修改:实体已被修改。
未更改:实体未修改。
分离:不跟踪实体。
实体生命周期中的状态变化
有时实体的状态是由上下文自动设置的,但也可以由开发人员手动修改。尽管从一种状态切换到另一种状态的所有组合都是可能的,但其中一些组合是毫无意义的。例如,将实体添加到已删除状态,反之亦然。
让我们讨论不同的状态。
不变状态
当实体未更改时,它绑定到上下文,但尚未被修改。
默认情况下,从数据库检索的实体处于此状态。
当实体附加到上下文(使用 Attach 方法)时,它同样处于 Unchanged 状态。
上下文无法跟踪它未引用的对象的更改,因此当附加它们时,它假定它们未更改。
分离状态
分离是新创建的实体的默认状态,因为上下文无法跟踪代码中任何对象的创建。
即使您在上下文的 using 块内实例化实体,也是如此。
分离甚至是禁用跟踪时从数据库检索的实体的状态。
当实体分离时,它不会绑定到上下文,因此不会跟踪其状态。
它可以被处置、修改、与其他类结合使用,或者以您可能需要的任何其他方式使用。
因为没有上下文跟踪它,所以它对实体框架没有任何意义。
添加状态
当实体处于已添加状态时,您几乎没有选择。事实上,你只能将其与上下文分离。
当然,即使您修改了某些属性,状态仍保持为“已添加”,因为将其移动到“已修改”、“未更改”或“已删除”是没有意义的。
它是一个新实体,与数据库中的行没有对应关系。
这是处于这些状态之一的基本先决条件(但该规则不是由上下文强制执行的)。
修改状态
当一个实体被修改时,这意味着它处于未更改状态,然后某些属性发生了更改。
实体进入 Modified 状态后,可以移动到 Detached 或 Deleted 状态,但即使手动恢复原始值,也无法回滚到 Unchanged 状态。
它甚至不能更改为“已添加”,除非您将实体分离并添加到上下文中,因为数据库中已存在具有此 ID 的行,并且在持久化它时会出现运行时异常。
已删除状态
实体进入已删除状态,因为它是未更改或已修改,然后使用了 DeleteObject 方法。
这是限制性最强的状态,因为从该状态更改为除分离之外的任何其他值都是毫无意义的。
如果您希望上下文控制的所有资源都在块末尾释放,则使用 using语句。当您使用using语句时,编译器会自动创建一个try/finally块并在finally块中调用dispose。
using (var context = new UniContext()) { var student = new Student { LastName = "Khan", FirstMidName = "Ali", EnrollmentDate = DateTime.Parse("2005-09-01") }; context.Students.Add(student); context.SaveChanges(); }
在处理长时间运行的上下文时,请考虑以下事项 -
当您将更多对象及其引用加载到内存中时,上下文的内存消耗可能会迅速增加。这可能会导致性能问题。
请记住在不再需要上下文时将其丢弃。
如果异常导致上下文处于不可恢复的状态,则整个应用程序可能会终止。
随着查询和更新数据的时间间隔增大,遇到并发相关问题的可能性也会增加。
使用 Web 应用程序时,每个请求使用一个上下文实例。
使用 Windows Presentation Foundation (WPF) 或 Windows 窗体时,请为每个窗体使用一个上下文实例。这使您可以使用上下文提供的更改跟踪功能。
经验法则
网络应用程序
现在,对于 Web 应用程序来说,每个请求都使用上下文是一种常见的最佳实践。
在 Web 应用程序中,我们处理的请求非常短,但保留了所有服务器事务,因此它们是上下文生存的适当持续时间。
桌面应用程序
对于桌面应用程序,如 Win Forms/WPF 等,上下文按表单/对话框/页面使用。
由于我们不希望将上下文作为应用程序的单例,因此当我们从一种形式转移到另一种形式时,我们将处理它。
通过这种方式,我们将获得很多上下文的能力,并且不会受到长期运行上下文的影响。