【问题标题】:Coldfusion - Complex object error when trying to cfloop over query. Version discrepancy?Coldfusion - 尝试对查询进行 cfloop 时出现复杂对象错误。版本差异?
【发布时间】:2016-03-01 16:34:28
【问题描述】:

前言:因此,我们需要将一些工作应用程序转移到新服务器上,因为我们正在淘汰旧的服务器,因此我不得不安装一个新的 CF 实例。

此应用程序在运行 ColdFusion 版本“9,0,0,251028”标准版(通过 ColdFusion 管理员)的旧服务器上运行良好。

在较新的服务器上,我使用的是 CF 2016 版本 2016.0.0.298074 开发者版(这是在谷歌搜索中弹出的第一件事,所以我选择了它)。

现在的问题:有一段代码给出了一个错误提示:

复杂对象类型不能转换为简单值。

表达式请求了一个变量或一个中间表达式结果作为一个简单的值。但是,结果不能转换为简单值。简单值是字符串、数字、布尔值和日期/时间值。查询、数组和 COM 对象是复值的示例。 错误的最可能原因是您尝试将复杂值用作简单值。例如,您尝试在 cfif 标记中使用查询变量。

错误发生在 G:/Gumbo/components/modules/resource/ResourceAdmin.cfc: line 282 从 G:/Gumbo/admin/modules/resource/action.cfm 调用:第 34 行 从 G:/Gumbo/admin/action.cfm 调用:第 19 行

281 cfloop query="getseq">
282 <cfif getseq.resourceCategoryID IS temp><cfset newseq = getseq.displaySeq ><cfbreak></cfif>
283 </cfloop>

违规行是 282。有问题的代码:

<cfloop query="getseq">
      <cfif getseq.resourceCategoryID IS temp><cfset newseq = getseq.displaySeq ><cfbreak></cfif>
</cfloop>

根据我的研究,我注意到 cfloop 在某些版本的 ColdFusion 上显然不适用于查询参数,但我不明白为什么新版本会导致我出现此错误。

所以我的问题是:

  1. 有没有办法以某种方式重新获取这个旧版本的 CF?请记住,我的旧计算机上有 CF9 源文件夹,但我不确定是否有办法获取源文件并将它们移动或手动安装它或其中的来龙去脉。是否可以像将旧源文件复制到新服务器上的新 CF 源一样简单?

  2. 更改上述代码的简单替代方法是什么?我对 CF 完全不熟悉,因为这是我在接受这份工作时继承的一个较旧的项目。我希望在较新的系统上获得确切的版本,但更改代码是唯一可行的选择。

任何见解将不胜感激。

编辑:

这是整个违规函数:

<cffunction name="updateResource" access="public" output="false" displayname="Update a Resource">       
    <cfset VARIABLES.dateUpdated=DateAdd("d", 0, arguments.dateUpdated)>    

    <cfquery datasource="#this.datasource#">
      update md_rlm_resource
      set published=<cfqueryparam cfsqltype="cf_sql_tinyint" value="#arguments.published#">,
          resourceName=<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.resourceName#">,
          resourceNumber=<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.resourceNumber#">,
          resourceAuthor=<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.resourceAuthor#">,
          resourceFile=<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.resourceFile#">,
          dateUpdated=<cfqueryparam cfsqltype="cf_sql_timestamp" value="#VARIABLES.dateUpdated#">,
          shortDescription=<cfqueryparam cfsqltype="cf_sql_longvarchar" value="#arguments.shortDescription#">
      where resourceID=<cfqueryparam value="#arguments.resourceID#" cfsqltype="cf_sql_integer">
    </cfquery>    

    <cfquery name="getseq" datasource="#this.datasource#">
      select displaySeq, resourceCategoryID
      from md_rlm_resourcecategoryrel
      where resourceID=<cfqueryparam value="#arguments.resourceID#" cfsqltype="cf_sql_integer">   
    </cfquery>

    <cfquery datasource="#this.datasource#">
      delete from md_rlm_resourcecategoryrel
      where resourceID=<cfqueryparam value="#arguments.resourceID#" cfsqltype="cf_sql_integer">
    </cfquery>

    <cfif IsDefined("arguments.resourceCategoryIDs")>
      <cfset resourceCategoryID = ArrayNew(1)>
      <cfset resourceCategoryID = ListToArray(arguments.resourceCategoryIDs)>

      <cfif #ListLen(arguments.resourceCategoryIDs)# gt 1>
        <cfset tmp1 = #ArrayLen(resourceCategoryID)#>
        <cfelse>
        <cfset tmp1 = "1">
      </cfif>

      <cfloop INDEX="idx" FROM="1" TO="#tmp1#">     
        <cfset newseq = 1>

        <cfif #tmp1# gt 1>
           <cfset temp=resourceCategoryID[idx]>
        <cfelse>
           <cfset temp=resourceCategoryID>        
        </cfif>

        <cfloop query="getseq">
          <cfif getseq.resourceCategoryID IS temp><cfset newseq = getseq.displaySeq ><cfbreak></cfif>
        </cfloop>

        <cfquery datasource="#this.datasource#">
          insert into md_rlm_resourcecategoryrel
             (resourceCategoryID, resourceID, displaySeq)
          values
            (
            <cfif #tmp1# gt 1>
            <cfqueryparam CFSQLTYPE="cf_sql_integer" VALUE="#resourceCategoryID[idx]#">,
            <cfelse>
            <cfqueryparam CFSQLTYPE="cf_sql_integer" VALUE="#resourceCategoryID#">,
            </cfif>       
             <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.resourceID#">,
             <cfqueryparam cfsqltype="cf_sql_float" value="#newseq#">)
        </cfquery>
      </cfloop>   
    </cfif> 

    <cfquery datasource="#this.datasource#">
    DELETE FROM md_rlm_resourceregionrel 
    WHERE resourceID=<cfqueryparam value="#arguments.resourceid#" cfsqltype="cf_sql_integer">
    </cfquery>

    <cfloop index="regionele" list="#arguments.regionID#" delimiters=",">
        <cfquery datasource="#this.datasource#">
        INSERT INTO md_rlm_resourceregionrel (resourceID, regionID) 
        VALUES (<cfqueryparam value="#arguments.resourceid#" cfsqltype="cf_sql_integer">, #regionele#)
        </cfquery>
    </cfloop>
</cffunction>

【问题讨论】:

  • 您可以在 cfrepo gpickin.com/cfrepo 上找到 ColdFusion 的存档版本至于您的错误 temp 是什么?如果您需要查看变量是什么,则可以通过cfdump 进行检查。
  • temp 是从另一个数据库表中获取的 resourceCategoryID 并进行比较以确保 ID 与我所知道的相同。它对我的理解没有影响,因为它在其他版本上都可以正常工作。立即查看 repo,感谢推荐!
  • 我们正在进行相同的迁移(CF 9 到 2016)。我建议您专注于重构代码库以解决此类差异,而不是坚持使用旧版本的 CF。您是否已转储查询的每一行的内容并为循环的每次迭代转储“temp”的值?到 2016 年,您可能有错误的数据以不同的方式解释。我们遇到了诸如 CF 9 运行的无效函数语法之类的问题,但 2016 年没有。在我们发布 2016 年之前,我们有一个项目专门解决这些类型的代码差异生产。
  • 你能给我们确切的错误吗,从屏幕上复制和粘贴,而不是解释。屏幕上的错误还将显示导致错误的确切语句,它不是来自您在此处提供给我们的代码。另外,当您说“我注意到 cfloop 显然不适用于查询参数”时……您说“参数”的地方是指“属性”吗?就像您认为 &lt;cfloop query&gt; 本身不适用于某些版本的 CF 一样?不是这种情况。除非在 CF2016 中引入了新错误(很有可能)。最后你能给我们一个合适的独立复制案例吗?
  • 已编辑以包含完整的错误消息和整个函数的代码 sn-p。基本上,该功能通过我们的 CMS 编辑资源,然后更新相关的数据库。

标签: coldfusion coldfusion-9 coldfusion-2016


【解决方案1】:

从这里:

<cfset resourceCategoryID = ListToArray(arguments.resourceCategoryIDs)>
...
<cfif #tmp1# gt 1>
    <cfset temp=resourceCategoryID[idx]>
<cfelse>
    <cfset temp=resourceCategoryID><!--- temp is now an array --->        
</cfif>

temp(可怕的变量名,顺便说一句)可能是一个数组。

然后你会这样做:

<cfif getseq.resourceCategoryID IS temp>

您不能使用 IS 运算符比较数组:IS 比较简单值。这就是您看到错误的原因。

顺便说一句,你没有 var-ing 代码中的任何变量,这是相当糟糕的形式,并且有可能在你的代码中出现“意外行为”。

【讨论】:

  • 感谢您的解释!我继承了这段代码,我同意这种形式很糟糕,而且我不知道冷融合,所以调试起来很痛苦。我正在寻找比较复杂数据类型的解决方案,并且我看到还有一个 EQUAL 和 EQ 命令,这些命令中的任何一个都适合数组吗?还是我必须将数组转换为列表然后进行比较?另外,为什么您怀疑旧 CF 版本(例如 9)不会引发此错误?
  • EQEQUALIS 都是相同的运算符。至于为什么它可能适用于旧版本?没有把握。也许——由于某种原因,我无法访问代码——它总是在 if 语句的 true 分支上运行。您可能能够使用oneArray.equals(anotherArray) 来比较两个数组吗? (参考:docs.oracle.com/javase/8/docs/api/java/util/…
  • 虽然equals(...) 可以工作,但它可能不是 IMO 的最佳选择。原因是它比典型的 CF 比较敏感得多。通常equals() 还考虑区分大小写和值数据类型。例如,元素 123 将被视为与 val(123) 不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-16
  • 2021-05-27
  • 1970-01-01
  • 2012-07-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多