实体框架:使用分离的对象和附加的对象

Posted

技术标签:

【中文标题】实体框架:使用分离的对象和附加的对象【英文标题】:Entity Framework: Working with detached objects and attached ones 【发布时间】:2010-09-28 05:08:31 【问题描述】:

首先,让我列出我想做的事情。假设我有EntityObjectMetaDataData1Data2 三种类型。正如人们所期望的那样,MetaData 引用了Data1Data2 中的每一个实例。现在,对于每个MetaData,我可以计算出一个value

到目前为止很简单。现在,我想让用户玩转Data1Data2 的各种组合,看看他们能得到什么values。这显然需要创建MetaData 的实例。现在,如果我不想用MetaData 的所有这些条目来混淆数据库,那么我想在内存上下文中创建实体对象而不调用SaveChanges() 将其写回数据库.但是,这会带来一个问题,即每当我尝试访问内存中 MetaDataData1Data2 引用时,都会遇到以下异常:

InvalidOperationException 未处理

当相关对象处于添加状态或分离状态并且最初不是使用 NoTracking 合并选项检索时,无法返回此 EntityCollection 或 EntityReference 的源查询。

如果我按照建议进行操作,并将对象“提交”到 DB,我最终会遇到混乱问题。

总之,有罪的代码看起来像这样:

MetaData temp = MetaData.CreateMetaData(0);

MetaData.Data1 = <existing Data1 from context>;
MetaData.Data2 = <existing Data2 from context>;

//Exception here
if (!MetaData.Data1Reference.isLoaded)
    MetaData.Data1Reference.Load();

this guy 似乎也有类似的问题。

【问题讨论】:

【参考方案1】:

IsLoaded 仅与已从数据库实现的实例的属性相关。正如您所发现的,对于尚未从数据库中具体化的实例,它不会返回有用的信息。

因此,您应该更改测试方式是否要调用 Load()。如果您知道您将使用仅在内存中创建而不是从数据库中具体化的 MetaData 实例,那么您可以编写如下代码:

if ((temp.EntityState != System.Data.EntityState.Added) && 
    (!temp.Data1Reference.IsLoaded)) temp.Data1Reference.Load();

我在这里掩盖了一些微妙之处。对于初学者,EntityState 是用 FlagsAttribute 声明的,因此它可以 contain 添加而不是 equal 添加。此外,如果 Data1Reference 不为空,则这些都不是必需的,因此您可能只想先测试一下。关键是,您可以编写适合您情况的代码,但它必须考虑 temp 的完整状态,而不仅仅是它的属性。

【讨论】:

“EntityState 是用 FlagsAttribute 声明的,所以它可以包含Added而不等于Added” - 那么它不应该是(temp.EntityState &amp; EntityState.Added) != EntityState.Added吗? @BlueRaja,是的,没错。我试图不离题。 所以,类似于:“(!temp.EntityState.HasFlags(System.Data.EntityState.Added)) && (!temp.Data1Reference.IsLoaded)) temp.Data1Reference.Load();”应该覆盖得更好吧?

以上是关于实体框架:使用分离的对象和附加的对象的主要内容,如果未能解决你的问题,请参考以下文章

无法附加分离的实体:“ObjectStateManager 中已存在具有相同键的对象”

实体框架 - 分离和重新附加实体?

在实体框架中将对象树附加到对象上下文

Asp.net 核心 - 实体框架核心 - 将附加数据添加到视图对象,同时保持它是可查询的

分离和附加后动画对象不继续动画

Spring JpaRepository - 分离和附加实体