在实体框架中,Add和Attach之间有什么区别,以及如何解决我的问题
本文关键字:何解决 解决 问题 我的 什么 Add 框架 实体 Attach 之间 区别 | 更新日期: 2023-09-27 17:50:43
我最近开始使用实体框架,检查是否真的需要向数据库添加新记录一直是一件很痛苦的事情。
如果我需要添加到数据库中的实体已经在上面了,我就会知道,因为我在插入它之前会进行查询,如果它存在,那么我会保留该实例,因为我需要在某些关系中使用它。
假设我的实体名称是Book
。
当一个实体不在数据库中时,问题就来了,而我在数据库中:
Book b = //...
modelContainer.AddToBooks(b);
我可以很容易地做到:
modelContainer.SaveChanges()
每次我添加一个新的实体(无论它是什么实体(,这都会很好,因为当我一次插入一种条目,并检查它是否已经在数据库中时,我不会有重复问题。
但是如果我想避免经常打SaveChanges()
怎么办
在这个问题中:是否可以检查一个对象是否已经附加到实体框架中的数据上下文?,这个问题的作者提供了一种方法,在我的情况下对我有帮助,但如果我把对象Add
而不是Attaching
放到上下文中,它就不起作用。
我的问题(可能是两个,但非常相关(是:Add和Attach之间的区别是什么?我如何解决我的问题
编辑:
这是我遇到的问题的一个例子。
我有一个实体Result
,它与另外两个实体有关系:Trainer
和Horse
。
我从外部源获取数据,所以我必须手动创建所有实体。
每次我需要插入一个新的Trainer
时,我都会这样做:
var trainer = Trainer.CreateTrainer(Id)
然后我查询数据库,看看数据库中是否已经有一个Id
的培训师。如果是,那么我将trainer
变量替换为数据库中的变量。
如果不是,我可以在这里做两件事:
- 将培训师连接到上下文(我可以使用密钥检查它是否已经存在(
- 将培训师添加到上下文中(使用
AddToTrainers(...)
(
与Horse
相同。
现在,当我需要创建一个新的Result
(包含Trainer
和Horse
(时,我会分配上一个训练器&马到那个结果实例。
我应该在这里做些什么才能将新的Result
添加到上下文中?
- 如果我附加了驯马师/马,那么当我附加结果时,我得到
InvalidOperationException
,告诉我驯马师已经在对象上下文中了 - 如果我添加培训师而不是附加它,我会得到另一个错误(现在记不起来了,但它告诉我数据库中已经有培训师了(
重要信息:
第一个错误在附加结果时给出,第二个错误在执行SaveChanges()
时给出。
这里我想避免的是每次添加新结果时调用SaveChanges()
。
ObjectContext
在内部跟踪所有通过上下文加载、附加或添加的实体。当调用SaveChanges
时,数据库中只能修改这些实体。每个这样的实体在CCD_ 23中具有一个CCD_。ObjectStateEntry
的主要特性之一是State
。状态为枚举类型EntityState
,提供以下值:
- 已添加
- 已删除
- 已分离
- 已修改
- 未更改
从数据库加载的每个实体都处于Unchanged
状态。脱离是一种特殊的状态。在ObjectStateManager
中找不到处于分离状态的ObjectStateEntry
。但是,如果您向ObjectStateManager
请求上下文未跟踪的实体的ObjectStateEntry
,它将创建一个具有Detached
状态的新ObjectStateEntry
。
现在Attach
和AddObject
之间的区别:
Attach
-如果调用此方法,ObjectContext
将开始跟踪整个对象图(主实体和所有相关实体(。所有尚未被跟踪的实体都将被设置为Unchanged
状态AddObject
-如果您调用此方法,ObjectContext
也将开始跟踪整个对象图(主实体和所有相关实体(。不同之处在于,所有尚未跟踪的实体都将设置为Added
状态(=必须设置为数据库的新对象(
我知道我发这篇文章有点晚了,但我一直在寻找类似的解决方案。。。然后我发现了这篇微软的文章,它可能简洁地回答了OP的大多数问题,并可能帮助未来的SO观众?:
添加/附加和实体状态==(http://msdn.microsoft.com/en-us/data/jj592676.aspx(
来自文章:
本主题将介绍如何将实体添加和附加到上下文,以及实体框架如何在SaveChanges期间处理这些实体。
具体参见该页的最后一节:
插入或更新模式:某些应用程序的常见模式是根据主键的值,将实体添加为新实体(导致数据库插入(或将实体附加为现有实体并将其标记为已修改(导致数据库更新(。