3

我发现一段代码可以在 ColdFusion 10 引擎下工作,但不能在 ColdFusion 2016 (CF12) 引擎下工作。

我有一个 CFC,其中包含由函数调用获取的缓存查询。假设我有一个要缓存的查询,但我对该查询使用的 db 表进行了更改。我没有看到返回的缓存查询中的数据,所以我需要刷新查询缓存,很简单。这就是我设置代码的方式:

<cffunction name="getVariables" access="public" returntype="query">
    <cfargument name="time_span" required="true" default="#this.cacheSpan#" />
    <cfset var qryGetVariables="">

    <!--- IF REFRESH, NEW QRYTIMESPAN --->
    <cfif arguments.time_span eq 0 AND NOT this.bln_refresh>
        <!--- IF time_span 0 but not refresh, reset to original cache span --->
        <cfset arguments.time_span = this.cacheSpan />
    </cfif>
    <cfquery name="qryGetVariables" datasource="#this.dsn#" cachedwithin="#arguments.time_span#">
        select *
          from get_variables
         order by id, value
    </cfquery>
    <cfreturn qryGetVariables>
</cffunction>

我在同一个 CFC 中调用一个函数,该函数以下列方式刷新此查询:

this.bln_refresh = true;
<cfinvoke method="getVariables" returnvariable="qryReturn">
   <cfinvokeargument name="time_span" value="0" />
</cfinvoke>
this.bln_refresh = false;

同样,这以前在 ColdFusion 10 上有效,但现在在 ColdFusion 2016 上无效。我需要做些什么来刷新这个特定查询的缓存?

4

3 回答 3

4

是的,这在 CF10 之后发生了变化。它被认为是错误,但仍未修复。一旦使用 缓存查询结果cachedWithin,就不能使用createTimeSpan(0, 0, 0, 0)(等于0)或任何负值使其无效。

演示

<!--- cache data for 10 minutes --->
<cfquery cachedWithin="#createTimeSpan(0, 0, 10, 0)#">
    SELECT `foo` FROM `example`;
</cfquery>

| 富
|-----
| 美国广播公司

让我们更改数据。

UPDATE `example` SET `foo` = 'DEF';

正如预期的那样......

<!--- invalidate cache and fetch new data --->
<cfquery cachedWithin="#createTimeSpan(0, 0, 0, 0)#">
    SELECT `foo` FROM `example`;
</cfquery>

| 富
|-----
| 国防军

现在让我们缓存最新的数据。

<!--- cache new data for 10 minutes --->
<cfquery cachedWithin="#createTimeSpan(0, 0, 10, 0)#">
    SELECT `foo` FROM `example`;
</cfquery>

结果在 CF10

| 富
|-----
| 国防军

cachedWithin <= 0使缓存的查询无效。因此下一个cachedWithin > 0将新数据存储在缓存中。

结果在 CF2016

| 富
|-----
| 美国广播公司

cachedWithin <= 0只是跳过了缓存。下一个cachedWithin > 0从缓存中获取。并且缓存没有改变。


更新

此错误的当前解决方法是使用 的cacheID属性,<cfquery>然后使用cacheRemove(theCacheID).

旧答案

您可以使用 使查询缓存无效<cfobjectcache action="CLEAR">它会使所有缓存的查询无效,这很糟糕。另一种选择是自己使用缓存查询cachePut并使用cacheGet.

这是一个提示如何做到这一点。您可能必须在这里合并您的this.cacheSpan逻辑,我不确定它的目标是什么:

<cffunction name="getVariables" access="public" returntype="query">

    <cfargument name="time_span" required="true" default="#this.cacheSpan#">

    <cfset var qryGetVariables = "">

    <cfset var cacheKey = "qryGetVariables"> <!--- make sure the key is unique and only used in this function --->
    <cfset var useCache = ((arguments.time_span lte 0) or this.bln_refresh)>

    <cfif useCache>
        <cfset qryGetVariables = cacheGet(cacheKey)>
    </cfif>

    <cfif not isQuery(qryGetVariables)>

        <cfquery name="qryGetVariables" datasource="#this.dsn#">
            select *
              from get_variables
             order by id, value
        </cfquery>

        <cfset cachePut(cacheKey, qryGetVariables, arguments.time_span)>

    </cfif>

    <cfreturn qryGetVariables>
</cffunction>
于 2017-06-27T20:26:06.680 回答
1

非常感谢@Alex,我遇到了以下似乎在我们的服务器上运行的解决方案:

<cffunction name="getVariables" access="public" returntype="query">
    <cfargument name="time_span" required="true" default="#this.cacheSpan#" />
    <cfset var qryGetVariables="" />
    <cfset var flt_qryTimeSpan=0>

    <cfif NOT cacheIdExists("qryGetVariablesCache") OR this.bln_refresh>
        <cfquery name="qryGetVariables" datasource="#this.dsn#" cachedwithin="#flt_qryTimeSpan#">
            select *
              from get_variables
             order by id, value
        </cfquery>
        <cfset cacheRemove("qryGetVariablesCache") />
        <cfset cachePut("qryGetVariablesCache",qryGetVariables,this.cacheSpan) />
    <cfelse>
        <cfset qryGetVariables = cacheGet("qryGetVariablesCache") />
    </cfif>
    <cfreturn qryGetVariables>

</cffunction>
于 2017-07-18T18:46:11.807 回答
0

我不知道@Alex 所说的是否正确,但我没有理由怀疑他。我没有运行 ColdFusion 2016。也许这是为特定查询刷新缓存的另一个选项......

请记住,当使用标签的cachedWithin属性时,cfquery它只会在以下所有条件都为真时缓存查询。“只有在Administrator中启用查询缓存才生效。要使用缓存数据,当前查询必须使用相同的SQL语句、数据源、查询名称、用户名和密码。 ”(cfquery文档

重点介绍这部分——同样的SQL语句。如果稍微更改 SQL 语句,缓存将被刷新。所以也许你可以在你的 SQL 语句中添加另一个条件来刷新查询。您甚至可以使用已有的相同变量time_span

我在想这样的事情(语法可能因您的 DBMS 而异):

<cfquery name="qryGetVariables" datasource="#this.dsn#" cachedwithin="#arguments.time_span#">
    select *
    from get_variables
    where '#arguments.time_span#' = '#arguments.time_span#'
    order by id, value
</cfquery>

条件应始终为真,因此查询将返回相同的结果集。

*我没有测试过这个。

于 2017-06-28T12:49:13.560 回答