确定实体代理的上下文是否已被释放

本文关键字:是否 释放 上下文 实体 代理 | 更新日期: 2023-09-27 18:00:40

在一个EF 6项目中,我正在为实体编写验证函数。有些是静态的,而另一些是实体本身的实例方法。

忽略这是否是一种糟糕的做法,我想检查实体是否是使用上下文创建的,如果是,它们是否仍然是附加的。

请注意,这些函数不能访问上下文对象,只能访问实体类。

例如,一个方法验证Department实体,并将验证级联到所有关联的Department.Employee实例。

  • 如果层次结构是手动创建的,则验证将成功
  • 如果层次结构是使用仍然有效的上下文创建的,则验证将成功,尽管速度较慢
  • 如果层次结构是使用已释放的上下文创建的,则验证将失败,并显示ObjectDisposedException(前提是启用了代理创建并且未使用.Include(***)

那么,问题是,在不访问DbContext实例的情况下,是否可以检测到上述场景?如果不是,我们如何才能最好地验证整个层次结构,而不管它们是如何创建的。

var result = true;
var departments = ???; // Constructed manually or through a DbContext instance.
foreach (var department in departments)
{
    result &= department.Validate();
    foreach (var employee in department.Employees)
    {
        result &= employee.Validate();
    }
}

编辑:请注意,这适用于不能具有长时间运行的DbContext实例的桌面应用程序。它们几乎总是在检索数据之后立即被处理。重新查询数据库似乎不是一个可行的验证选项,因为它是由琐碎的用户输入触发的,会降低整个用户体验。

确定实体代理的上下文是否已被释放

根据您的问题

请注意,这些函数不能访问上下文对象,只能访问实体类。

脑海中浮现出两种解决方案,但没有一种真正令人满意:

  1. 构建自己的跟踪器,并以某种方式使其可用于这些方法
  2. 向实体中添加一些内容,例如查询上下文时设置的WasLoaded属性。WasLoaded可以由
    1. 编写设置它的EF拦截器
    2. 添加一个所有值都设置为1的人工bit列。然后将其映射到属性;如果您在上下文之外构造属性,则该属性将为false,如果从上下文加载,则为true

跟踪器似乎是最干净的,因为它不会污染你的模型。如果你不关心你的模型,拦截器是一个不错的选择。

虽然它不能直接回答你的问题,但你可以避免使用代理,在这种情况下,无论你的验证是以相同的方式进行的,因为你的模型在内存中。不过,也有一些常见的权衡需要考虑。

我不确定你是怎么发现最后一种情况的。我想你可以让你的追踪器追踪更多的实体。。。让它也跟踪上下文的状态。