多次将 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);
        }
    }
}

这适用于初始页面加载和第一次回发。但是,在后续回发中,它会失败并显示以下错误:

具有临时实体键值的对象不能附加到对象上下文。

奇怪的事情(无论如何,对我来说)是当我在 VS 调试器中单步执行代码并检查 review 的属性时。EntityKey,IsTemporary 字段为假。

关于我应该如何解决此问题的任何建议?我试过打电话.附件("评论",评论),但我最终得到同样的错误。

到目前为止,我想我所知道的是,当我制作第一个.附加调用,它附加"review"对象,但由于它是一个引用对象,它也修改了 Session 中的对象并向其添加 EntityKey(我在这里的术语或理解可能不正确 - 这对我来说是 EF 中的一个薄弱领域)。所以现在,在第一次回发之后,我的会话对象已被"附加"。第二次(当它失败时),它已经被附加了,所以它失败了?

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

任何建议不胜感激。

编辑:我应该在有人回答之前提到这一点,但我无法在每次回发时返回数据库以获取评论。会话中的对象稍后会修改,其数据可能与数据库中的数据不同。

我会从您的会话变量中获取实体,它的 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);         
        }
    }
}
这是一个简单的更改,并且使您将

整个对象存储在会话中有点无关紧要,但是如果您无法更改,这应该可以为您解决问题。

更新

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

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

这些问题通常是实体框架在附加对象时的工作方式的结果。 附加实体时,将以递归方式附加它引用的每个实体。 例外具有误导性,因为我们自然会认为错误出在我们显式附加的实体上,而在许多情况下,问题出在隐式附加的实体上。

因此,我不确定您的代码片段有多短,但似乎您可能正在尝试附加引用新创建的实体的实体。

最新更新