Tom Muck

Alpha Dog Blues Band
Home page
All articles
All Extensions | Extension News | Extension FAQs | Customer Login
Books authored or co-authored by Tom Muck
Extensions, books, and other products | Customer Login
Your current cart contents
Tom-Muck.com Blog | CMXTraneous Blog | Flash Remoting Blog
About the site

Blog

Tom Muck's Blog: Persistent CFCs and CFQUERYTom Muck's Blog

News and Views

Persistent CFCs and CFQUERY

Thursday, June 30, 2005 7:39:58 PM

I wrote this in my article on persistent CFCs for Community MX last week, but it's worth repeating here because I see a lot of people using CFCs in session and application scope that do not take this into account: you should always declare local variables at the top of your <cffunction> tag:

<cffunction name="blah" returntype="any">
<cfset var i = 0>
<cfloop from="0" to="10" index="i">
<!--- Some code --->
</cfloop>
</cffunction>

Many people are doing this, but I wonder how many people apply the same principle to recordsets within the CFQUERY tag. . . .I see this a lot:

<cffunction name="testRS" access="public" output="false">
  <cfquery name="rs" datasource="Northwind">
  SELECT * FROM Products
  </cfquery>
  <cfreturn rs>
</cffunction>

If this is in a persistent scope, the variable rs will be available even after the return call. In fact, it will hang around for the life of the persistent CFC. To properly scope the query, you should declare it first:

<cffunction name="testRS" access="public" output="false">
  <cfset var rs = "">
  <cfquery name="rs" datasource="Northwind">
  SELECT * FROM Products
  </cfquery>
  <cfreturn rs>
</cffunction>

Now, the rs query will be destroyed after the function returns the variable to the caller -- it is not persisted within the CFC. You can try it like this. Create a cfc:

<cfcomponent>

<cffunction name="testRS" access="public" output="false">
<cfquery name="rs" datasource="Northwind">
SELECT * FROM Products
</cfquery>
<cfreturn rs>
</cffunction>

<cffunction name="testRSBad" access="public" output="false">
<cfreturn rs>
</cffunction>

</cfcomponent>

The function testRSBad() looks like it should throw an error, because rs is not defined, however if this is in persistent state and you hit the testRS() method first, then rs is persisted for the entire session.

Try it out: make sure you have sessions turned on in the Application.cfm file. Then put some code on a page called testrs.cfm:

<a href="testrs.cfm?hit=true">Next page</a>

<cfif not isdefined("url.hit")>
  <cfset session.user1 = createobject("component","testuser")>
  <cfset session.user1.testRS()>
</cfif>

<cfdump var=#session.user1.testRSBad()#>

You have a link to the page, and you are instantiating the session instance of the CFC only once -- when you preview the page. When you hit the link, you will see the page again with the same recordset dumped out, but this time it is coming from the leftover persisted global variable rs that was not scoped properly in the CFC.

Category tags: Community MX, Dreamweaver, ColdFusion

Before posting comments or trackbacks, please read the posting policy.

Full Blog Calendar

Pay me securely with your Visa, MasterCard, Discover, or American Express card through PayPal!
Pay me securely with your Visa, MasterCard, Discover, or American Express card through PayPal!
About | Privacy Policy | Contact | License Agreement | ©2002-2024 Tom Muck | Dreamweaver Extensions