2012-06-11 57 views
1

因此,我正在研究将实体存储在Session变量中的现有应用程序,并且每次回发都尝试将其重新附加到新的上下文。我不特别关心这个实现,但现在重写它已经不成问题了。该代码看起来是这样的:不止一次地将EF4实体附加到上下文

public partial class ReviewDetail 
{ 
    DBContext context = new DBContext(); 

    public void Page_Load(object sender, EventArgs e) 
    { 
     if (!Page.IsPostBack) 
     { 
      int id = Convert.ToInt32(Request.QueryString["id"]); 
      Session["Review"] = context.Reviews.FirstOrDefault(x => x.ReviewID = id); 
     } 
     else 
     { 
      Review review = Session["Review"] as Review; 
      context.Attach(review); 
     } 
    } 
} 

此作品在两个初始页面加载和第一回发。然而,在后续的回传,它失败,错误如下:

使用临时的EntityKey值的对象不能被附加到对象上下文。

奇怪的事情(对我来说)是,当我通过VS调试器中的代码并检查review.EntityKey的属性时,IsTemporary字段为false。

有关我该如何解决此问题的任何建议?我尝试过打电话.AttachTo(“评论”,审查),但我最终有同样的错误。

我认为迄今为止我在做第一个.Attach调用时,会附加“review”对象,但由于它是一个引用对象,因此它也会修改Session中的对象,并将EntityKey添加到它(我可能对我的术语或我的理解不正确 - 对我来说这是EF中的一个弱点)。所以现在,在第一次回发之后,我的Session对象被“附加”了。第二次(当它失败时),它已经被连接,所以它失败了?

我想我在正确的轨道上,只是不知道如何从这里接近修复。理想情况下,我们不会这样做,但重写它以使用更正确的方法可能不会发生在这里,除非没有其他选择。

任何建议表示赞赏。

编辑:我应该在有人回答之前提到过这个问题,但我不能在每次回复时回到数据库以获得评论。会话中的对象稍后会进行修改,它的数据可能与数据库中的数据不同。

回答

2

我会从你的会话变量的实体,它的ID属性重新查询方面,如:

public partial class ReviewDetail 
{ 
    DBContext context = new DBContext(); 

    public void Page_Load(object sender, EventArgs e) 
    { 
     if (!Page.IsPostBack) 
     { 
      int id = Convert.ToInt32(Request.QueryString["id"]); 
      Session["Review"] = context.Reviews.FirstOrDefault(x => x.ReviewID = id); 
     } 
     else 
     { 
      Review review = Session["Review"] as Review; 

      Review updateReviewFromContext = context.ApplyCurrentValues<Review>("Reviews", review);   
     } 
    } 
} 

这是一个简单的变化,使得它有点不相干,你存储整个对象会议,但如果你不能改变,这应该为你做的伎俩。

UPDATE

参见:http://msdn.microsoft.com/en-us/library/dd487246

ApplyCurrentValues将你的更新从会话Review和应用其更新的属性是从上下文中返回的实体。唯一的窍门是你必须知道EntitySetName是什么,在我的例子“评论”中,但只要这不会改变,它就可以被硬编码。

+0

我应该在我原来的帖子中提到我不能这么做。我们在会话中存储它的具体原因是,会话中的对象与数据库中的对象不同。在我意识到他们这样做的原因之前,我确实尝试过。 :) – Scott

+0

因此,在会话版本有变化的情况下,如果您从数据库中获取它们,您将失去这些更改? – CodingGorilla

+0

正确。修改后的数据保存在会话对象中,直到点击“保存”按钮为止。 Page_Load和按钮单击事件之间可能会有多次回发。通过这个例子,这个应用程序要复杂得多,我已经写了足够的东西来给出这个问题的概念。 – Scott

1

这些问题通常是由于Entity Framework在附加对象时如何工作的结果。当您附加实体时,您将递归地附加它引用的每个实体。这些例外是误导性的,因为我们自然地认为错误与我们明确附加的实体有关,在很多情况下,问题与隐式附加的实体有关。

所以,我不确定你的代码片断是多么的缩写,但似乎你可能试图附加一个引用新创建的实体的实体。

+0

我不认为这是这种情况。只是因为我可以加载一个新的新页面,导致一个简单的回发(它不创建任何新的实体),然后再做一个相同类型的回发(再次,没有新的实体),它会引发错误。 – Scott

+0

如果你改变'context.Reviews.FirstOrDefault(x => x.ReviewID = id);'context.Reviews.Find(id);'? –

相关问题