2014-11-19 2 views
1

Надеюсь, вы можете мне помочь. Обычно я читаю переменные сеанса в локальной переменной, так что мне не нужно создавать бесконечные блокировки чтения. Но я натолкнулся на какое-то интересное поведение. Обратите внимание, что я не применял никаких блокировок записи для краткости:Чтение значения из переменной сеанса в локальную переменную в Coldfusion

Рассмотрим следующий пример:


Пример 1:

<cfset session.testvalue = 1 /> 
<cfset lcktestvalue = session.testvalue /> 
<cfoutput>#lcktestvalue#</cfoutput><br /> 
<cfset session.testvalue = 2 /> 
<cfoutput>#lcktestvalue#</cfoutput> 

ВЫХОД:


Пример 2:

<cfset session.testvalue1.item = 1 /> 
<cfset lcktestvalue1 = session.testvalue1 /> 
<cfoutput>#lcktestvalue1.item#</cfoutput><br /> 
<cfset session.testvalue1.item = 2 /> 
<cfoutput>#lcktestvalue1.item#</cfoutput> 

ВЫВОД:


Я пытаюсь понять, почему второй пример, обновляет 'lcktestvalue1.item', когда значение читалось только один раз? я ожидал бы пример 1 & 2 для получения такого же выхода, и следующий, чтобы произвести выход второго примера по:


Пример 3:

<cfset session.testvalue1.item = 1 /> 
<cfset lcktestvalue1 = session.testvalue1 /> 
<cfoutput>#lcktestvalue1.item#</cfoutput><br /> 
<cfset session.testvalue1.item = 2 /> 
<cfset lcktestvalue1 = session.testvalue1 /> 
<cfoutput>#lcktestvalue1.item#</cfoutput> 

ВЫХОД:


Единственная причина такого поведения, о котором я могу думать, состоит в том, что второй пример использует структуру внутри структуры. Но я не могу расширить эту концепцию. Ты можешь? Мне действительно нужно это понять, потому что я создаю корзину для покупок, которая широко использует методологию в примере 2. На самом деле это работает нормально, но я не уверен, почему, и я боюсь под нагрузкой, она может потерпеть неудачу?

Благодарим за помощь, которую вы можете мне дать.

+0

"Бесконечные блокировки чтения"? Какую версию CF вы используете? Если вы не имеете дело с некоторыми фанковыми условиями гонки, вам, вероятно, вообще не нужно фиксировать переменные сеанса. –

+0

Лучше быть в безопасности, чем сожалеть. Я слышал немало страшных историй о состоянии сеанса, даже с CF10. Из того, что я прочитал, есть несколько ошибок, а это значит, что эта проблема до сих пор не полностью решена Adobe. –

ответ

6

Charles, ожидается поведение. Структуры и объекты передаются по ссылке - это означает, что вы на самом деле просто устанавливаете указатель на ячейку памяти для доступа к базовому объекту.Когда набор оператор имеет дело с примитивного (строка, число, дата и т.д.), то копии данных в вашей новой переменной - так это:

<Cfset session.testvalue = 1/> 
<cfset testvalue = session.testvalue/> 

... на самом деле создает 2 места каждая из которых содержит "1"

Когда вы имеете дело с объектом, однако (структура, компоненты, функция запроса и т.д. - ничего не примитивного), как это:

<cfset session.testvalue.item1 = 1/> 
<cfset testvalue = session.testvalue/> 

variable.testvalue переменная на самом деле является указателем на структуру , которую вы создали в инструкции set (session.testvalue.item1 неявно создает структуру).

Это важный фундаментальный материал - особенно при работе с CFC, функциями, областями применения и т. Д. Это сообщение на Primitive vs complex variables объясняет это более подробно.

Это не имеет никакого отношения к блокировке. Если у вас нет какой-либо демонстративной гонки, вам не нужно переходить с помощью блокировки.

Я хотел бы отметить, что ваша практика здесь, вероятно, не отличная идея, - вероятно, вы должны быть обзорной ваш местный ВАР, как variables.varName любым способом, в этом случай толкая переменные сессии в эту области видимости не экономит никаких усилий.

ПРИМЕЧАНИЕ. Пока я писал этот Рэй, вкратце сжатый ответ был точно до точки (пока я был многословным).

ПРИМЕЧАНИЕ 2: В ColdFusion имеется один нюанс, который некоторые неожиданно обнаруживают - массивы передаются по значению (в виде копии) и не по ссылке. Это может иногда вас бросить - и если вы когда-либо делаете массив объектов

+0

Извините, Рэй, я убедился и отметил, что вы сначала ответили на это. –

+0

Спасибо, Марк. Отличное объяснение. Могу ли я сделать вывод, что мои значения SESSION по-прежнему безопасны. Предположительно, у указателя есть скрытый sessionid, который также различает много разных сеансов пользователей? –

+0

Не уверен, что вы просите, но если вы имеете в виду безопасный, как в привязанном к пользователю, то нам. Существует sessionID (который может принимать несколько форм в CF), привязанный к файлу cookie.В вашем конкретном примере вы можете испортить данные _per user_, но не через пользователей. Для этого вам нужно будет использовать тот же подход с переменными приложения: D –

9

Потому что ваш второй пример делает указатель или ссылку от исходного значения до нового значения. Вы можете думать, что это мнимая строка между двумя такими, что когда кто-то меняется - другой тоже. Это происходит со структурами. Вы можете обойти это, используя дубликат.

Но NOTE! Необходимость одержимо перемещать переменные session/app/server НЕ требуется в течение почти десяти лет. Вам все равно придется беспокоиться о гоночных условиях, но в 99% случаев это не ваша забота.

+0

Ray. Спасибо за этот очень сжатый и визуально привлекательный ответ. Мне нравится идея струны. Раньше я читал значения сеанса в локальной переменной, так что я мог избежать многочисленных блокировок чтения, но, я думаю, старые привычки умирают! –

0

Вы должны использовать Duplicate(), если хотите скопировать/клонировать структуру, а не просто ссылаться на объект, хранящийся в SESSION.

<cfset session.testvalue1.item = 1 /> 
    <cfset lcktestvalue1 = Duplicate(session.testvalue1) /> 
    <cfoutput>#lcktestvalue1.item#</cfoutput><br /> 
    <cfset session.testvalue1.item = 2 /> 
    <cfoutput>#lcktestvalue1.item#</cfoutput> 

Выход

1 
    1 

Coldfusion WikiDocs

Смежные вопросы