所以我正在开发一个现有的应用程序,它将一个实体存储在一个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对象已被“附加”。第二次(当它失败时),它已被附加,所以它失败了?
我认为我走在正确的轨道上,不知道如何从这里开始修复。理想情况下,我们不会这样做,但重写它以使用更正确的方法可能不会在这里发生,除非没有其他选择。
任何建议都表示赞赏。
编辑:我应该在有人回答之前提到这一点,但我不能回到每个回发的数据库来获取评论。会话中的对象稍后会被修改,它的数据可能与数据库中的数据不同。
答案 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)
这些问题通常是实体框架在附加对象时的工作方式的结果。附加实体时,会以递归方式附加它引用的每个实体。这些例外具有误导性,因为我们自然会假设错误与我们明确附加的实体有关,而在许多情况下,问题是与隐式附加的实体有关。
所以,我不确定你的代码片段有多缩写,但似乎你可能试图附加一个引用新创建实体的实体。