ChatGPT解决这个技术问题 Extra ChatGPT

实体框架代码优先 - DbContext 上没有 Detach() 方法

我想知道为什么 DbContext 对象上没有像 ObjectContext 那样的 Detach 方法。我只能假设这种遗漏是故意的,但我很难弄清楚为什么。我需要能够分离和重新附加实体(例如,用于将缓存放入 ASP.NET 项目中)。但是,由于我无法分离实体,所以当我尝试附加与先前上下文关联的实体时,我得到“一个实体对象不能被多个 IEntityChangeTracker 实例引用”异常。

这里有什么指导?我错过了什么吗?

有没有人要说的:“这里的指导是什么?我错过了什么吗?”就个人而言,我只对在寻找从上下文中读取实体的解决方案时使用 Detach 感兴趣,就在保存从 UI 返回的实例之前。这给了我“ObjectStateManager 中已经存在具有相同键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。”

J
Joakim

对于可能偶然发现这个问题的人,从 CTP5 开始,您现在需要编写

((IObjectContextAdapter)context).ObjectContext

为了到达 ObjectContext。


+1 干净,优雅,一个衬里。我喜欢它。还想指出,该接口专门在这里找到: System.Data.Entity.Infrastructure.IObjectContextAdapter 是的,就像 Pandincus 指出的那样,您也必须引用 System.Data.Entity 。
我得到“找不到 IObjectContextAdapter”,它建议安装实体框架。肯定是安装的。
M
Morteza Manavi

DbContext 在内部使用 ObjectContext 并且 EF 团队将其作为受保护的属性提供,以防万一您需要下拉到较低级别的 API,听起来就是这种情况,因此您可以使用或公开派生的所需功能数据库上下文:

public class YourContext : DbContext 
{
    public void Detach(object entity) 
    {
        ObjectContext.Detach(entity);            
    }
}

然后你可以从你的控制器调用这个方法来分离一个实体。

或者,您可以将其更改为拥有更丰富的 API:

public class YourContext : DbContext
{
    public void ChangeObjectState(object entity, EntityState entityState)
    {
        ObjectContext.ObjectStateManager.ChangeObjectState(entity, entityState);
    }
}

以下是元数据中 DbContext 的样子:

public class DbContext : IDisposable 
{      
    protected System.Data.Objects.ObjectContext ObjectContext { get; }
    ...
}

@Stacker 这不是答案,因为它需要上面所选答案中概述的演员表,即 DbContext 实现 IObjectContextAdapter 给它 ObjectContext 否则无法访问的属性。结合2个答案给出@splite的答案如下
ChangeObjectState 非常懒惰,它使用“带演员阵容的线性算法”……有点……你知道……非常糟糕。
J
Jan 'splite' K.

EF:CF 4.1 RC1 和 EF:CF 4.1 RTW 具有相同的显式实现的 IObjectContextAdapter:

public static class DbContextExtensions
{
    public static void Detach(this System.Data.Entity.DbContext context, object entity)
    {
         ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext.Detach(entity);
    }
}

微软决定“分离技术太先进,应该隐藏”。恕我直言,发明这个的人应该被枪杀——因为如果你添加全新的实体,否则很难在不对 db 进行更改的情况下将其删除(你可以使用 DbEntityEntry 进行操作,但那是另一回事了)。

4年后编辑:

使用 EF6(我不知何故跳过了 EF5 :))您不再需要 detach(),因为删除新添加的条目不会像在 EF4 中那样生成 delete from [table] where [Id] = 0 - 您只需调用 mySet.Remove(myFreshlyCreatedAndAddedEntity) 一切都会没事的。


射击?反正谁需要这个功能? :P
@quetzalcoatl:var context = ...; var poco = new Poco(); context.Add(poco); context.Remove(poco); <--- 抛出异常,因为你必须 DETACH 它,而不是删除 - 嘿,分离是隐藏的......
(编辑消失了 5 分钟,sry :))当时我很生气......当你制作 Windows 应用程序时,你必须有一些方法来“取消创建新的,可能不完整的条目,但保留 UoW 上下文”.. . 我们摆脱了整个 EF 顺便说一句,并编写我们自己的 ORM:没有办法利用延迟加载(我有一堆发票,我无法在单个“其中 InvoiceId 在(xxyy)”查询中加载每个 InvoiceItem - 包括不起作用以我们预期的方式),更大的存储库非常懒惰(在每次执行之前进行线性(!!!)搜索,wtf ...),为 100 多种 poco 类型创建代理需要太多时间等等......
最后顺便说一句,我正在谈论用于生产的大型(= 5 名程序员全职工作 2 年)应用程序(= 媒体中的人们将用它赚钱),其中快速(且丰富多彩 :)))应用程序是好应用程序。我们必须“弯曲”一些东西以使其超快...具有 1k+ 条目的组合框(在特定的而非通用的情况下,您可以或不能 CRUD 条目)角色管理?必须在 0.2s 以下...如果您编写 ASP 或小应用程序,它不会那么痛苦;)
Heyheyhey..我在开玩笑,注意最后的“:P”:)似乎我不小心设法骗到了你,对不起:)我完全同意你的看法。没有真正的附加/分离支持使得框架对于任何重要的用途都非常有限,这就是为什么它们在较新版本的 EF 中被引入。从你给出的数字来看,这听起来像是一个“中等”项目和数据库,并不是真正的庞大,但这是非常主观的,我不知道你的项目。无论如何,根据我的经验,大多数 ORM/DB 问题不是来自 ORM,而是来自定义不明确的业务逻辑,或者来自不是为通过 ORM 使用而设计的 DB。
S
Stefan Michev

我通常使用以下属性扩展基类(从 DbContext 继承):

public class MyDbContext : DbContext
{
    public ObjectContext ThisObjectContext
    {
        get
        {
            return ((IObjectContextAdapter)this).ObjectContext;
        }
    }
}

稍后您可以将此属性用于各种有用的东西......比如分离:)