views:

1045

answers:

2

Situation: Object in session from a past context can't be set as another object's parent since other object is in a new context.

Say I have a User in session that I had retrieved from a context. Now the page reloads, that context has been dismissed, and a new context is made.

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

Page Reload

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

What I would like to do is:

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

The idea is that if the object in session does not belong to the current context, reload it from the database so that it is now "owned" by the same context as every other object in the current context. (I am using a context per request)

UPDATE

So I did this temporarily until I can get a better idea of how to fix this:

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

The idea is to see if the object in session (sessionUser) is the same as the one "in" the context. Now the if works just fine. First time the context is created, that SHOULD hit the database and grab the user. Once compared, it's obvious they are not the same and the sesionUser is now the user in the context. Next time that if is checked, the sessionUser and the userToCheck are the same.

Problem still is the :

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

ALWAYS hits the database. This is not a good solution.

More Update

Meh this may be the answer after all. I had forgotten this rule:

x is an property of type ObjectQuery. When you execute an ObjectQuery, it will always hit the backing store. That’s what they do. If you don’t want to execute a database query, then don’t use an ObjectQuery.

+1  A: 

Why not just check the user id?

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

Or you might just detach the user object from the old context and attach it to the new context using Context.Attach().

Daniel Brückner
ID doesn't work. It will actually grab the user from the database defeating the idea of checking the context for that user. You second suggestion I'll have to try.
Programmin Tool
A: 

Ok got it.

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

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

The GetObjectByKey method which is described as:

GetObjectByKey tries to retrieve an object that has the specified EntityKey from the ObjectStateManager. If the object is currently not loaded into the object context, a query is executed in an attempt to return the object from the data source.

Did some testing and it does what it says. The first time through (context was created on request) it hits the database and checks that object against what's in session. The two are not the same so it sets the sessionUser to the new object, thus now having the sessionUser in the context and in session. Next time around the GetObjectByKey method only checks the context (As Profiler showed no database interaction). Yay.

Programmin Tool