Ошибка с неопределенными переменными при циклическом выполнении запроса

У меня ошибка при циклическом выполнении запроса с использованием cfloop.

Когда я использую cfdump в запросе (заметьте, внутри цикла), я прекрасно вижу все данные. Но когда я пытаюсь получить значение каждой переменной, как вы обычно это делаете в cfloop, я получаю сообщение о том, что они не определены. Затем я изменил каждую переменную, чтобы она ссылалась конкретно на запрос, и теперь проблема в том, что переменная не определена в запросе. Вот код:

<cffunction name="writeCourses">
<cfargument name="recordset" required="yes" type="query">
     <cfif recordset.RecordCount NEQ 0>
         <cfset temp = "">  
         <cfoutput>
         <cfloop query="recordset">     
         <!--- <cfdump var="#recordset#"> <cfabort/> --->  

            <cfset temp = temp & "<strong>#recordset.courseType# #recordset.courseNum# ">
            <cfif isDefined("recordset.courseTHM") AND recordset.courseTHM EQ 1>
                <cfset temp = temp & "(#left(recordset.courseNum,3)#4) ">
            </cfif>
            <cfif isDefined("recordset.courseName")>
                <cfset temp = temp & "#recordset.courseName# </strong><br>">
            </cfif>
            <cfset temp = temp & "#recordset.courseDESC#<br>">
            <cfset temp = temp & "#recordset.courseHours#<br><br>">
        </cfloop>
        </cfoutput>
     <cfelse>
        <cfset temp = "">
     </cfif>
 <cfreturn temp>
</cffunction>

Как видите, каждая переменная заключена в теги ##. Первоначально ни один из них не был обработан recordset., но они все еще не были определены. И когда я раскомментирую теги cfdump и cfabort, они работают нормально, и я вижу запрос recordset со всеми данными, как и должно быть.

Каждый раз, когда я использовал cfloop с запросом, он работал, как и ожидалось. Кроме того, я не писал этот код, мне приходится его модифицировать (первоначальный автор здесь больше не работает).

Вот пример дампа recordset:

введите здесь описание изображения

Сообщение об ошибке:
Сведения: [пустая строка]
ErrNumber: 0
Сообщение: Элемент COURSETTYPE не определен в RECORDSET.
Разрешенное имя: RECORDSET

Строка ошибки:

   <cfset temp = temp & "<strong>#recordset.courseType# #recordset.courseNum# ">   
   <cfif isDefined("recordset.courseTHM") AND recordset.courseTHM EQ 1>
   <cfset temp = temp & "(#left(recordset.courseNum,3)#4) ">
   </cfif>
   <cfif isDefined("recordset.courseName")>
   <cfset temp = temp & "#recordset.courseName# </strong><br>">
   </cfif>

Это все одна строка :/

Хранимая процедура/функция, вызывающая вышеуказанное:

<cffunction name="getCoursesByDept">
<cfargument name="deptCode" required="yes" type="string">
<CFSTOREDPROC procedure="dbo.GetCourses"     datasource="WebCatalog">
    <CFPROCPARAM type="IN" dbvarname="@deptCode" value="#deptCode#" cfsqltype="CF_SQL_CHAR">
    <CFPROCRESULT name="result">
</CFSTOREDPROC>
<cfinvoke method="writeCourses" recordset="#result#" returnvariable="output">
<cfreturn output>
</cffunction>

person mAlenius    schedule 16.04.2013    source источник
comment
Не могли бы вы показать нам вывод <cfdump> (или хотя бы его часть, показывающую набор записей)?   -  person Miguel-F    schedule 16.04.2013
comment
Добавление некоторых примеров сейчас.   -  person mAlenius    schedule 16.04.2013
comment
На какую переменную и строку указывает ошибка? Можете ли вы поделиться фактическим сообщением об ошибке?   -  person Miguel-F    schedule 17.04.2013
comment
Вот первая часть: Detail [пустая строка] | Номер ошибки 0 | Элемент сообщения COURSETTYPE не определен в RECORDSET. | Resolvedname RECORDSET |. Если у меня просто #courseType вместо #recordset.courseType#, я просто получаю сообщение о том, что COURSETYPE не определен.   -  person mAlenius    schedule 17.04.2013
comment
Предполагая, что temp было определено где-то ранее. Возможно, с <cfparam name="temp" default=""> или <cfset temp = "">?   -  person Chester    schedule 17.04.2013
comment
О, и сообщение об ошибке находится в строке, где впервые используется coursetype, с идентификатором CF_DOTRESOLVER Редактировать: Честер, да, в строке перед <cfoutput> есть <cfset temp = "">   -  person mAlenius    schedule 17.04.2013
comment
@mAlenius: Пожалуйста, отредактируйте свой вопрос, чтобы включить эту информацию. Комментарии непостоянны и, как вы можете видеть, мало что позволяют форматировать.   -  person ale    schedule 17.04.2013
comment
Спасибо, надо было сделать это в самом начале.   -  person mAlenius    schedule 17.04.2013
comment
Вы получаете ошибку на первой итерации цикла? Я не вижу ничего плохого в вашем коде, и вы правы; в этом случае вам не нужно указывать recordset. для ваших переменных. Не могли бы вы также показать нам свой <cfquery>, определяющий набор записей?   -  person Miguel-F    schedule 17.04.2013
comment
Я сделал это без recordset, переменные все еще не определены. Итак, вы предлагаете мне проверять нулевые значения (на случай, если первый проход будет прослушиваться)?   -  person mAlenius    schedule 17.04.2013
comment
Вам не нужно этого делать. Даже если значение равно NULL, переменная все равно будет определена (просто пуста в ColdFusion). Я не уверен, что происходит. Ваш код выглядит нормально. Можете ли вы поделиться своим <cfquery> кодом, определяющим набор записей?   -  person Miguel-F    schedule 17.04.2013
comment
возможно ли, что набор записей является зарезервированным словом? В противном случае код выглядит хорошо для меня.   -  person Matt Busche    schedule 17.04.2013
comment
Это результат хранимой процедуры, которая отлично работала в других местах. Я посмотрел на cfinvoke, который вызывает метод, содержащий приведенный выше код, и кажется, что recordset проходит нормально. На самом деле не хочу публиковать всю хранимую процедуру, но в основном она вытягивает строки, где тип равен переданному параметру (строка).   -  person mAlenius    schedule 17.04.2013
comment
@MattBusche Возможно, посмотрю. В настоящее время объявлен как единственный параметр функции, в которой содержится этот код...   -  person mAlenius    schedule 17.04.2013
comment
Просто выстрел в темноте.. 1) Процедура всегда возвращает набор результатов? 2) Кроме того, если задействован cfc, может ли это быть проблемой с потоками? Не могли бы вы опубликовать код функции и вызов cfinvoke?   -  person Leigh    schedule 17.04.2013
comment
Я только что смоделировал код, и это не зарезервированное слово. Если ваш запрос не дал результатов, он не попадет в ваш <cfset>, значит, что-то не опубликовано, что идет не так.   -  person Matt Busche    schedule 17.04.2013
comment
@mAlenius, можете ли вы опубликовать хранимую процедуру без аргументов, которые вы передаете?   -  person Matt Busche    schedule 17.04.2013
comment
@ Ли 1) Да, это так. Если он ничего не может найти, он возвращает запрос, содержащий сообщение об ошибке (т. е. курс не найден). 2) Нет cfc, вызов функции и вызов хранимой процедуры находятся в одном файле .cfm.   -  person mAlenius    schedule 17.04.2013
comment
Обновлен ОП. Теперь содержит полную функцию, окружающую цикл, а также сохраненный вызов процедуры для запроса и вызов функции, в которой передается запрос. Готово в течение дня и посещаю вечерние занятия, поэтому я не смогу при необходимости вытащить фактические образцы кода.   -  person mAlenius    schedule 17.04.2013
comment
после вашего <cfargument> вы можете сделать <cfset var recordset = arguments.recordset>   -  person Matt Busche    schedule 17.04.2013
comment
Конечно, есть ли причина, по которой хранимый процесс возвращает пустые строки? Строки с 4 по 12 не содержат данных.   -  person Chester    schedule 17.04.2013
comment
@Chester Похоже, он просто свернул эти строки, когда делал скриншот.   -  person Matt Busche    schedule 17.04.2013
comment
@mAlenius - Re .. возвращает запрос, содержащий сообщение об ошибке. Это означает, что столбцы курса не всегда существуют в наборе результатов, о чем сообщает сообщение об ошибке. Первая строка кода использует эти столбцы без предварительной проверки их существования. Кроме того, сообщение об ошибке действительно должно генерироваться в CF, а не внутри процедуры. Задача процедуры — просто вернуть данные. Кроме того, вам действительно нужно локализовать функциональные переменные result, output, temp и так далее. Отсутствие области видимости var может создать проблемы даже на одной странице, если вы повторно используете имена переменных.   -  person Leigh    schedule 17.04.2013


Ответы (2)


Ваша проблема, по-видимому, заключается в отсутствии охвата. Вот ваши первые 4 строки:

<cffunction name="writeCourses">
<cfargument name="recordset" required="yes" type="query">
 <cfif recordset.RecordCount NEQ 0>
     <cfset temp = "">  

Попробуйте это так:

<cffunction name="writeCourses">
<cfargument name="recordset" required="yes" type="query">
<cfset var temp = "">  
<cfif arguments.recordset.RecordCount NEQ 0>

Различия заключаются в использовании ключевого слова var для вашей локальной переменной temp и добавлении области аргументов к переменной набора записей.

person Dan Bracuk    schedule 16.04.2013
comment
Это помогло; спасибо :) Я также добавил проверки isDefined для каждой переменной, это тоже могло помочь. - person mAlenius; 17.04.2013
comment
@mAlenius не используйте isDefined() вместо этого используйте structKeyExists(structure,value) - person Matt Busche; 17.04.2013

(В дополнение к комментариям Дэна...)

Если [процедура] ничего не может найти, она возвращает запрос, содержащий сообщение об ошибке (т.е. курс не найден)

Тогда это означает, что столбец COURSETYPE не всегда существует в resultset, о чем сообщает сообщение об ошибке. Если процедура возвращает любой результат, независимо от содержимого, будет выполнен код внутри блока cfif. Поскольку первая строка кода использует этот столбец, без проверки его существования это приведет к той же ошибке, которую вы видите.

Кроме того, как я упоминал в комментариях, вам действительно нужно локализовать переменные функций result, output, temp и так далее. Отсутствие области видимости var может создать проблемы даже на одной странице, если вы повторно используете имена переменных. Как предложил @Dan, вы должны полностью охватить все переменные, в частности, функцию arguments.

(Кроме того, я понимаю, что вы модифицируете существующий код, но сообщение об ошибке действительно должно обрабатываться в CF, а не внутри процедуры. Работа процедуры состоит только в том, чтобы возвращать данные. Код CF должен проверять RecordCount и примите соответствующие меры, если записи не найдены.)

person Leigh    schedule 17.04.2013
comment
Хранимая процедура просто возвращает пустой запрос, если ничего не найдено; Я изначально неправильно прочитал. - person mAlenius; 17.04.2013
comment
Хм.. это не соответствует описанной вами ошибке ;-) Но рад, что теперь это работает. - person Leigh; 17.04.2013