将EF4实体多次附加到上下文

时间:2012-06-11 18:33:44

标签: c# asp.net entity-framework

所以我正在开发一个现有的应用程序,它将一个实体存储在一个Session变量中,每个回发都会尝试将它重新附加到一个新的上下文。我并不特别关心这个实现,但现在重写它是不可能的。代码看起来像这样:

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);
        }
    }
}

这适用于初始页面加载和FIRST回发。然而,在后续回发中,它失败并出现以下错误:

具有临时EntityKey值的对象无法附加到对象上下文。

奇怪的是(对我来说,无论如何)是当我逐步调试VS调试器中的代码并检查review.EntityKey的属性时,IsTemporary字段为false。

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

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

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

任何建议都表示赞赏。

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

2 个答案:

答案 0 :(得分: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);         
        }
    }
}

这是一个简单的改变,并且使你在整个会话中存储整个对象有点无关紧要,但是如果你不能改变它,这应该为你做到了。

<强>更新

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

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

答案 1 :(得分:1)

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

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