.net 是否可以检查对象是否已附加到实体框架中的数据上下文?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1715501/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is is possible to check if an object is already attached to a data context in Entity Framework?
提问by joshcomley
I am getting the following error when trying to attach an object that is already attached to a given context via context.AttachTo(...):
尝试通过以下方式附加已附加到给定上下文的对象时出现以下错误context.AttachTo(...):
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
ObjectStateManager 中已存在具有相同键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。
Is there a way of achieving something along the lines of:
有没有办法实现以下方面的目标:
context.IsAttachedTo(...)
context.IsAttachedTo(...)
Cheers!
干杯!
Edit:
编辑:
The extension method Jason outlined is close, but it doesn't work for my situation.
Jason 概述的扩展方法很接近,但它不适用于我的情况。
I am trying to do some work using the method outlined in the answer to another question:
我正在尝试使用另一个问题的答案中概述的方法做一些工作:
如何使用 Linq to Entities 从我的表中删除一行或多行*而不*首先检索行?
My code looks a bit like this:
我的代码看起来有点像这样:
var user = new User() { Id = 1 };
context.AttachTo("Users", user);
comment.User = user;
context.SaveChanges();
This works fine, except when I do something else for that user where I use the same method and try to attach a dummy Userobject. This fails because I have previously attached that dummy user object. How can I check for this?
这很好用,除非我为那个用户做其他事情,我使用相同的方法并尝试附加一个虚拟User对象。这失败了,因为我之前已经附加了那个虚拟用户对象。我该如何检查?
采纳答案by joshcomley
Here's what I ended up with, which works very nicely:
这是我最终得到的结果,效果非常好:
public static void AttachToOrGet<T>(this ObjectContext context, string entitySetName, ref T entity)
where T : IEntityWithKey
{
ObjectStateEntry entry;
// Track whether we need to perform an attach
bool attach = false;
if (
context.ObjectStateManager.TryGetObjectStateEntry
(
context.CreateEntityKey(entitySetName, entity),
out entry
)
)
{
// Re-attach if necessary
attach = entry.State == EntityState.Detached;
// Get the discovered entity to the ref
entity = (T)entry.Entity;
}
else
{
// Attach for the first time
attach = true;
}
if (attach)
context.AttachTo(entitySetName, entity);
}
You can call it as follows:
您可以按如下方式调用它:
User user = new User() { Id = 1 };
II.AttachToOrGet<Users>("Users", ref user);
This works very nicely because it's just like context.AttachTo(...)except you can use the ID trick I cited above each time. You end up with either the object previously attached or your own object being attached. Calling CreateEntityKeyon the context makes sure it's nice and generic and will work even with composite keys with no further coding (because EF can already do that for us!).
这非常有效,因为它就像context.AttachTo(...)你每次都可以使用我上面提到的 ID 技巧。您最终会得到先前附加的对象或您自己的对象。调用CreateEntityKey上下文可确保它很好且通用,甚至可以使用复合键而无需进一步编码(因为 EF 已经可以为我们做到这一点!)。
回答by Mosh
A simpler approach is:
一个更简单的方法是:
bool isDetached = context.Entry(user).State == EntityState.Detached;
if (isDetached)
context.Users.Attach(user);
回答by jason
Try this extension method (this is untested and off-the-cuff):
试试这个扩展方法(这是未经测试和现成的):
public static bool IsAttachedTo(this ObjectContext context, object entity) {
if(entity == null) {
throw new ArgumentNullException("entity");
}
ObjectStateEntry entry;
if(context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry)) {
return (entry.State != EntityState.Detached);
}
return false;
}
Given the situation that you describe in your edit, you might need to use the following overload that accepts an EntityKeyinstead of an object:
鉴于您在编辑中描述的情况,您可能需要使用以下接受 anEntityKey而不是 object 的重载:
public static bool IsAttachedTo(this ObjectContext, EntityKey key) {
if(key == null) {
throw new ArgumentNullException("key");
}
ObjectStateEntry entry;
if(context.ObjectStateManager.TryGetObjectStateEntry(key, out entry)) {
return (entry.State != EntityState.Detached);
}
return false;
}
To build an EntityKeyin your situation, use the following as a guideline:
要EntityKey在您的情况下建立一个,请使用以下作为指导:
EntityKey key = new EntityKey("MyEntities.User", "Id", 1);
You can get the EntityKeyfrom an existing instance of Userby using the property User.EntityKey(from interface IEntityWithKey).
您可以通过使用属性(来自 interface )EntityKey从现有实例中获取。UserUser.EntityKeyIEntityWithKey
回答by Daniel Elliott
Using the entity key of the object you are trying to check:
使用您要检查的对象的实体键:
var entry = context.ObjectStateManager.GetObjectStateEntry("EntityKey");
if (entry.State == EntityState.Detached)
{
// Do Something
}
Kindness,
善良,
Dan
担
回答by Lawrence
This does not directly answer OPs question but this is how I solved mine.
这并没有直接回答 OP 的问题,但这就是我解决我的问题的方法。
This is for those who are using DbContextinstead of ObjectContext.
这适用于那些使用DbContext而不是ObjectContext.
public TEntity Retrieve(object primaryKey)
{
return DbSet.Find(primaryKey);
}
DbSet.Find Method:
DbSet.Find 方法:
Finds an entity with the given primary key values. If an entity with the given primary key values exists in the context, then it is returned immediately without making a request to the store. Otherwise, a request is made to the store for an entity with the given primary key values and this entity, if found, is attached to the context and returned. If no entity is found in the context or the store, then null is returned.
查找具有给定主键值的实体。如果上下文中存在具有给定主键值的实体,则它会立即返回,而无需向商店发出请求。否则,将向存储请求具有给定主键值的实体,如果找到该实体,则将其附加到上下文并返回。如果在上下文或存储中未找到实体,则返回 null。
Basically, it returns the attached object of the given primaryKeyso you just need to apply the changes on the returned object to keep the right instance.
基本上,它返回给定的附加对象,primaryKey因此您只需要在返回的对象上应用更改即可保留正确的实例。

