2

情况:来自过去上下文的会话中的对象不能设置为另一个对象的父对象,因为另一个对象位于新上下文中。

假设我在会话中有一个从上下文中检索到的用户。现在页面重新加载,该上下文已被解除,并创建了一个新上下文。

someUser = context.First(user => user.id == id);
Session["SomeUser"] = someUser
...
context.Dispose();

页面重新加载

userAddress = new UserAddress();
userAddress.User = (User)Session["SomeUser"]; //BOOM NOT IN SAME CONTEXT

我想做的是:

if(!context.SomeUsers.Contains((User)Session["SomeUSer"]) //Only check context NOT DATABASE
{
   //Reload from database
   //Set user in session to new object
}

这个想法是,如果会话中的对象不属于当前上下文,则从数据库中重新加载它,以便它现在由与当前上下文中的所有其他对象相同的上下文“拥有”。(我使用每个请求的上下文)

更新

所以我暂时这样做了,直到我能更好地了解如何解决这个问题:

Int32 sessionUser = sessionUser .UserID;
var userCheck = EntityContext.Context.ChatUsers.First(item => item.UserID == returnValueID);
if (userCheck != sessionUser)
{
   sessionUser = userCheck;
}

这个想法是查看会话中的对象(sessionUser)是否与上下文中的对象相同。现在 if 工作得很好。第一次创建上下文时,应该访问数据库并获取用户。一旦比较,很明显它们是不一样的,并且 sessionUser 现在是上下文中的用户。下次如果选中,sessionUser 和 userToCheck 是相同的。

问题仍然是:

var userCheck = EntityContext.Context.ChatUsers.First(item => item.UserID == returnValueID);

总是命中数据库。这不是一个好的解决方案。

更多更新

嗯,毕竟这可能是答案。我忘记了这条规则:

x 是 ObjectQuery 类型的属性。当您执行 ObjectQuery 时,它总是会命中后备存储。他们就是这样做的。如果您不想执行数据库查询,请不要使用 ObjectQuery。

4

2 回答 2

2

好的,我知道了。

ChatUser userCheck = (ChatUser)EntityContext.Context.GetObjectByKey(returnValue.EntityKey);

if(userCheck != returnValue)
{
   sessionUser = userCheck;
}

GetObjectByKey 方法描述为:

GetObjectByKey 尝试从 ObjectStateManager 检索具有指定 EntityKey 的对象。如果对象当前未加载到对象上下文中,则执行查询以尝试从数据源返回对象。

做了一些测试,它按照它说的做了。第一次通过(根据请求创建上下文)它会访问数据库并根据会话中的内容检查该对象。两者不同,因此它将 sessionUser 设置为新对象,因此现在 sessionUser 在上下文和会话中。下一次 GetObjectByKey 方法只检查上下文(因为 Profiler 显示没有数据库交互)。耶。

于 2009-03-24T14:40:41.513 回答
0

为什么不只检查用户 ID?

context.Users.Any(user => user.Id = ((User)session["SomeUser"]).Id)

或者,您可能只是将用户对象从旧上下文中分离出来,然后使用 Context.Attach() 将其附加到新上下文。

于 2009-03-23T23:42:28.987 回答