Структура сущности:Есть ли способ проверить, есть ли в контексте объект?
-
21-08-2019 - |
Вопрос
Ситуация:Объект в сеансе из прошлого контекста не может быть установлен в качестве родительского другого объекта, поскольку другой объект находится в новом контексте.
Допустим, у меня есть Пользователь в сеансе, которого я извлек из контекста.Теперь страница перезагружается, этот контекст был удален, и создается новый контекст.
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 работает просто отлично.При первом создании контекста он ДОЛЖЕН попасть в базу данных и захватить пользователя.После сравнения становится очевидно, что они не совпадают, и sesionUser теперь является пользователем в контексте.В следующий раз, когда будет проверен этот if, sessionUser и userToCheck будут одинаковыми.
Проблема по-прежнему заключается в :
var userCheck = EntityContext.Context.ChatUsers.First(item => item.UserID == returnValueID);
ВСЕГДА попадает в базу данных.Это не очень хорошее решение.
Дополнительные обновления
В конце концов, это может быть ответом.Я совсем забыл это правило:
x - это свойство типа ObjectQuery.Когда вы выполняете ObjectQuery, он всегда попадает в хранилище резервных копий.Это то, что они делают.Если вы не хотите выполнять запрос к базе данных, то не используйте ObjectQuery.
Решение
Ладно, понял.
ChatUser userCheck = (ChatUser)EntityContext.Context.GetObjectByKey(returnValue.EntityKey);
if(userCheck != returnValue)
{
sessionUser = userCheck;
}
Метод GetObjectByKey , который описывается как:
GetObjectByKey пытается извлечь объект, у которого есть указанный EntityKey из ObjectStateManager.Если объект в данный момент не загружен в контекст объекта, выполняется запрос в попытке вернуть объект из источника данных.
Провел некоторое тестирование, и оно делает то, что написано.При первом прохождении (контекст был создан по запросу) он попадает в базу данных и проверяет этот объект на соответствие тому, что находится в сеансе.Это не одно и то же, поэтому он присваивает sessionUser новому объекту, таким образом, теперь sessionUser находится в контексте и в сеансе.В следующий раз метод GetObjectByKey проверяет только контекст (поскольку профилировщик не показал взаимодействия с базой данных).Ура.
Другие советы
Почему бы просто не проверить идентификатор пользователя?
context.Users.Any(user => user.Id = ((User)session["SomeUser"]).Id)
Или вы можете просто отсоединить пользовательский объект от старого контекста и присоединить его к новому контексту с помощью Context.Attach().