使用具有Http Request生存期的ObjectContext时附加实体

时间:2009-11-04 08:38:18

标签: entity-framework

我在ASP.NET MVC应用程序中使用.NET 3.5 SP1。

在使用具有Http Request生命周期的ObjectContext并尝试附加上下文中存在的实体ALREADY时,我们收到错误: “ObjectStateManager中已存在具有相同键的对象.ObjectStateManager无法使用相同的键跟踪多个对象。” 例如,代码:

Category newCategory = new Category {CategoryId = CategoryIdSelected};
ctx.AttachTo("CategorySet", newCategory);
如果ObjectContext中存在CategoryId = CategoryIdSelected的'Category',

将会出错。

用于检查现有实体的修改代码:

Category newCategory = new Category {CategoryId = CategoryIdSelected};
ObjectStateEntry stateEntry = null;

if( ctx.ObjectStateManager.TryGetObjectStateEntry(newCategory, out stateEntry)){
   //EntityObject already attached in context, get it
    newCategory = (EntityObject)stateEntry.Entity;
}else{
    ctx.AttachTo("CategorySet", newCategory);   
}

修改后的代码仍然提供相同的错误: “[System.InvalidOperationException] = {”ObjectStateManager中已存在具有相同键的对象。 ObjectStateManager无法使用相同的键跟踪多个对象。“

请指教?

谢谢


问题补充:

使用具有Http Request生命周期的ObjectContext时附加实体的更多问题。

例如,如果我们有“AppUser”,“类别”和部门实体。

public class AppUser : System.Data.Objects.DataClasses.EntityObject{   
 public int Uid {get; set;}   
 public string UserName {get; set;}   
 public string Password {get; set;}   
 public Department Dept {get; set;}   
 public Category catg {get; set;}
 ...........   
}

AppUser与部门和类别实体有关系。 现在尝试附加'用户'时:

user = new AppUser{Uid=1,catg = new Category {categoryId=10}, Dept = new Department{departmentId=101}, ...}
var key = ctx.CreateEntityKey("AppUserSet", user);
if (ctx.ObjectStateManager.TryGetObjectStateEntry(key, out stateEntry)) {

仅在上下文中起作用

  • 没有categoryId = 10和
  • 的类别
  • 没有DepartmentId = 101
  • 的部门

一个选项是通过始终使用NOMERGE NoTracking选项检索来确保上下文没有附加实体。但我发现MergeOption.NoTracking存在以下问题:

  • 第二次调用仍然会导致数据库命中
  • 您没有在EntityRefs上获得EntityKeys。所以XXXReference的EntityKey为null,这意味着没有FK Stub。 Please see
    如何获取参考的EntityKey没有加载两端(两个实体)?
  • 即使Entity是Detached,它们也引用了DataContext(通过entity._realtionships._context)。 Please see.

请告知。

谢谢。

1 个答案:

答案 0 :(得分:0)

您的代码使用两种不同的上下文。你检查一个,然后附加到另一个:

if( csContext. //...){
   ///
}else{
    ctx. // ...
}

该实体似乎位于ctx,但不在csContext。我的建议是尽可能一次只使用一个上下文;它不那么令人困惑。

<强>更新

好的,你已经改变了问题中的代码。

我的猜测是你的存根对象没有EntityKey,所以TryGetObjectStateEntry返回false。尝试:

if( ctx.ObjectStateManager.TryGetObjectStateEntry(
    new EntityKey("MyEntities.CategorySet", "CategoryId", CategoryIdSelected), 
    out stateEntry)){

显然,将“MyEntities”替换为实际的型号名称。