Entity Framework - 生命周期

生命周期

上下文的生命周期在创建实例时开始,在实例被处理或垃圾收集时结束.

  • 当我们使用ORM时,上下文生命周期是一个非常重要的决定.

  • 上下文是执行类似于实体缓存,因此它意味着它保存对所有已加载实体的引用,这些实体的内存消耗可能会非常快,并且还可能导致内存泄漏.

  • 在下图中,您可以通过Context查看从应用程序到数据库的数据工作流程的上层,反之亦然.

数据工作流程

实体生命周期

实体生命周期描述实体的过程创建,添加,修改,删除等.实体在其生命周期中有许多状态.在查看如何检索实体状态之前,让我们看看什么是实体状态.状态是类型 System.Data.EntityState 的枚举,它声明以下值 :

  • Added:该实体已标记为已添加.

  • Deleted:该实体已标记为已删除.

  • Modified:该实体已被修改.

  • Unchanged:该实体尚未修改.

  • Detached:实体不是跟踪.

实体生命周期中的状态变化

有时设置实体状态由上下文自动完成,但也可由开发人员手动修改.即使从一个州到另一个州的所有开关组合都是可能的,但其中一些是没有意义的.例如,实体添加到已删除状态,反之亦然.

让我们讨论不同的状态.

未更改状态

  • 当实体未更改时,它绑定到上下文但它没有已被修改.

  • 默认情况下,从数据库中检索的实体处于此状态.

  • 当实体附加到上下文时(使用Attach方法),它同样处于Unchanged状态.

  • 上下文无法跟踪对它没有引用的对象的更改,所以当它们被附加时,它假定它们是不变的.

分离状态

  • Detached是新创建的实体的默认状态,因为上下文无法跟踪代码中任何对象的创建.

  • 即使你在上下文的使用块中实例化实体也是如此.

  • 分离是甚至是在禁用跟踪时从数据库中检索的实体的状态.

  • 当实体分离时,它不会绑定到上下文,所以其状态未被跟踪.

  • 可以将其处理,修改,与其他类组合使用,或以您可能需要的任何其他方式使用.

  • 因为没有上下文跟踪它,它对实体框架没有意义.

已添加状态

  • 当实体处于已添加状态时,您几乎没有选项.实际上,你只能将它从上下文中分离出来.

  • 当然,即使你修改了一些属性,状态仍然是Added,因为将它移动到Modified,不变或删除是没有意义的.

  • 这是一个新实体,与数据库中的行没有对应关系.

  • 这是进入其中一个州的基本先决条件(但上下文并未强制执行此规则).

已添加状态

已修改状态

  • 当实体被修改时,这意味着它处于Unchanged状态,然后某些属性被更改.

  • 实体进入Modified状态后,它可以移动到Detached或Deleted状态,但即使手动恢复原始值,它也无法回滚到Unchanged状态.

  • 除非你拒绝,否则它甚至不能改为添加ach并将实体添加到上下文中,因为数据库中已存在具有此ID的行,并且在持久化时会出现运行时异常.

已删除状态

  • 实体进入Deleted状态,因为它是Unchanged或Modified,然后是DeleteObject方法已经使用了.

  • 这是限制性最强的状态,因为它从这个状态变为除了Detached之外的任何其他值都是毫无意义的.

使用语句,如果您希望将上下文控制的所有资源放置在块的末尾.当您使用 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应用程序,使用上下文是一种常见且最佳的做法每个请求.

  • 在Web应用程序中,我们处理的请求非常短但保留所有服务器事务,因此它们是上下文生存的适当持续时间in.

桌面应用程序

  • 对于桌面应用程序,如Win Forms/WPF等,每个表单/对话框/页面都使用上下文.

  • 由于我们不希望将上下文作为我们应用程序的单例,因此当我们从一个表单移动到另一个表单时,我们将处理它.

  • 在此方式,我们将获得很多上下文的能力,不会受到长期上下文的影响.