Skip navigation
Currently Being Moderated

Passing Dates to a cfc

Sep 20, 2010 9:27 PM

I am trying to pass a date to a  cfc and get a numeric response

I test the service in Flashbuilder and it works fine when I type in a value of 09/20/2010

It returns the numeric sum as expected....

 

If I change the cfc to a string and refresh the service this also works (2010/09/20)

 

But when I try to call it nothing and I mean nothing works.

Not this....

                   var theDate:Date = new Date();

                   sumDateLineItemsResult.token = lineItemsService.sumDateLineItems(theDate);

                     lineItemsService.commit();

nor this....
                sumDateLineItemsResult.token = lineItemsService.sumDateLineItems(new Date(2010,09,20));
                lineItemsService.commit();

 

nor a call with a string variable after the cfc has been modified to accept strings....

 

The cfc...

 

    <cffunction name="sumDateLineItems" output="false" access="remote" returntype="numeric" >
        <cfargument name="theDate" type="date" required="true" />
        <cfset var qSum="">
        <cfquery name="qsum" datasource="BlueRose">
             SELECT SUM(Price) AS daysTotal FROM LineItems WHERE AptDate =  <CFQUERYPARAM CFSQLTYPE="CF_SQL_DATE"                 VALUE="#ARGUMENTS.theDate#">
        </cfquery>
        <cfif len(qsum.daysTotal) EQ 0>
            <cfset qsum.daysTotal="0">
        </cfif>
        <cfreturn qsum.daysTotal>   
    </cffunction>

 

It seems to simple and obvious but I am stumped ! Any help from a coldfusion maven would be greatly appreciated.

Thanks

Dan Pride

 
Replies
  • Currently Being Moderated
    Sep 21, 2010 5:50 AM   in reply to Daniel Pride

    Not too sure about the Flash side, but try setting the argument type to "any", then dumping out the arguments scope to an email so you can see exactly what CF receives when you call it.

     

    O.

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 21, 2010 7:32 AM   in reply to Daniel Pride

    Are you sure that you are using Actionscript's Date object constructor as intended?  The month parameter should be zero based.

     

    new Date(2010,8,20).

     

    Things to check/try:

     

    1. Is there a communication problem between your Flex client and all services on your CF server or just this one function?

     

    2. Use ServiceCapture or a similar tool to look at what is being sent from the client to the server.

     

    http://www.kevinlangdon.com/serviceCapture/

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 21, 2010 8:59 AM   in reply to Daniel Pride

    My answer to date-passing issues in any situation is usually to put my date in a clearly-defined string format (YYYYMMDD works well), pass the string, and parse it back into a date at the other end.At the moment, you've got implied conversion, and it may or may not be working the same way all the time.

     

    Just make sure it's date, not string, when it gets into your query, or you'll slow the query down (assuming your date field is indexed).

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 22, 2010 12:14 AM   in reply to Daniel Pride

    Give this a go matey:

     

    <cffunction name="sumDateLineItems" access="remote" returntype="void" >
        <cfargument name="theDate" type="any" required="true" />
        <cfmail to="me@myemail.com" from="site@mysite.com" subject="Function Arguments" type="html">
            <cfdump var="#ARGUMENTS#" />
        </cfmail>
    </cffunction>

     

    And don't you dare come back saying "but that's not my email address"

     

    P.S.

    "I am just getting into coldfusion after a long waste of time in zend  php" - glad to hear you finally left the dark side

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 22, 2010 1:26 AM   in reply to Daniel Pride

    Languages that are not object oriented to begin with should never attempt it.

     

    You know you are describing CF as well, when you say that?  It's only had any sense of OO for the last three versions.

     

    As for your code:

    * VAR all your variables in your functions;

    * I would be very hesitant about having a call to a DB within a loop.  Can you not move this process into the DB?  Even passing the DB a list of dates would be better than hitting the DB separately for each iteration of the array.

     

    --
    Adam

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 22, 2010 2:34 AM   in reply to Adam Cameron.

    * VAR all your variables in your functions;

    * I would be very hesitant about having a call to a DB within a loop.  Can you not move this process into the DB?  Even passing the DB a list of dates would be better than hitting the DB separately for each iteration of the array.

     

    --
    Adam

     

    I've never been quite sure what effect "VAR"ing has - could you expand?

     

    Agreed about doing your looping at DB level if at all possible.

     

    What's the problem with the code as it stands? What is is doing, or not doing?

     

    I don't know what underlying DB you're using, but it should have some sort of function to convert a string to a date. I'd suggest wrapping that round the parameter in your SQL, to make the conversion explicit rather than implicit. It should improve performance slightly, and you'll be sure that what you're getting is what you intend.

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 22, 2010 2:45 AM   in reply to JaneUK

    The "var" keyword puts a variable into the highest scope possible; in the case of a function this makes the variable viewable inside the function only.

     

    As an example:

     

    <cffunction name="test"...>

      <cfset mynum = 1 />

    </cffunction>

     

    <cfoutput>#mynum#</cfoutput>

     

    In the above example, you've set a variable inside a function, but that's now accessible *outside* that function, which is almost always not what you want. If you did <cfset var mynum = 1 /> then the page would error, as mynum would fall out of scope when your function ends.Not var'ing your variables means you can end up with a large number of variables on your page which either you're not aware are there or could end up inadvertendly overwriting a variable of the same name.

     

    In many languages this is the default behaviour, irritatingly in CF it's not.

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 22, 2010 3:25 AM   in reply to Owain North

    Thanks, Owain, all is now clear. Well, "var" is now clear, anyway

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 22, 2010 4:30 AM   in reply to Daniel Pride

    I don't use Flashbuilder myself, but when I write CFCs for those who do, they prefer me to pass them a query. I don't know their reasons for this, but I assume they have some.

     

     

    Why pass dates as text, not Date? If you can pass as "date", then yes, that's the best - just as long as you're absolutely sure that both ends mean the same thing by "date". It's the most common thing for any driver to mess up, sometimes in quite subtle ways. But you're not, are you?

     

    VALUE="#ARGUMENTS.dateToSum[i]#">

     

    You have quotes around your date. CF is converting a date to a string, in whatever unspecifed format it thinks is a good idea. Then your database (whatever it is) takes that string, realises it ought to be a date, and converts it back - again, making its own guesses as to what format it's in. If CF and database make slightly different assumptions, you have a problem. If you specify the format in both places, it's back under control.

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 22, 2010 5:50 AM   in reply to Daniel Pride

    Each trip to the DB has a reasonably high overhead, getting the call ready, (re-)establishing the connection, making the call, waiting for the DB to get the response organise, sending it back, closing the connection.  This is a non-trivial percentage of the entire DB call. So it's best to minimise the number of hits to the DB where possible.

     

    Equally, I usually find when code is looping and then querying within a loop, it's actually splitting the logic between CF & DB because it's convenient for the developer, as opposed to being the best approach, which is usually just to ask the DB to be more work, rather than CF & DB both splitting it.  I'm not saying this is intrinsically the case in all situations, but it's definitely always a red flag to (re)assess how things are being done.

     

    --

    Adam

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 22, 2010 5:53 AM   in reply to Daniel Pride

    I would also hope that Adobe talking to Adobe would use the same definition of "date", but I'm paranoid when it comes to dates, having had problems with them far too often in the past. Adobe talking to MySQL, though.... don't go there!

     

    Repeated calls to the DB from inside a loop should work, its a performance issue, as you say. If what you need is all dates for a month, that's only 30-odd calls, so not a problem.

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 22, 2010 6:05 AM   in reply to Adam Cameron.

    Just to emphasise Adam's point here, I just knocked up a test page with two methods - the first did 1000 queries to insert one row each, the second looped 1000 times to create one query, then executed it. Results were thus:

     

    One Query: 28 ms 
    1000 Queries: 713 ms

     

    So yes there's a significant performance increase in only using one query where possible. I appreciate in this case only about 30 rows are being inserted, so let's try that:

     

    One Query: 3 ms 
    30 Queries: 25 ms

     

    Bear in mind this table only had an id, a number and a string. More complex tables will have even longer execution times.

     

    Sorry for going a little off-subject, just something I've always meant to test properly. Must admit, using fewer database calls is actually even more efficient than I'd expected.

     

    O.

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 22, 2010 6:26 AM   in reply to Daniel Pride

    I wouldn't bother using Date[] - it should imply an array of dates yes, but CF is so loosely typed that if you want convenience just use "array" as the returntype and argumenttype.

     

    As long as you can get Flash to submit to the cfc use the cfmail/cfdump combo from earlier, the cfdump output will tell you exactly what CF is receiving from flash and what datatypes it determines it as.

     

    O.

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 22, 2010 8:05 AM   in reply to Daniel Pride

    You might try using the CF debugger to troubleshoot your server side code.

     

    http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859 461172e0811cbec0d389-7ffd.html

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 23, 2010 3:47 AM   in reply to Daniel Pride

    Using <cfqueryparam cfsqltype="cf_sql_date">, and pass it a date object.

     

    Also read this sectionof the dcos regarding # usage:

    http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859 461172e0811cbec22c24-7ff1.html

     

    --

    Adam

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 23, 2010 3:49 AM   in reply to Daniel Pride

    Without reading the whole thread again, is there any reason you're not using CFQUERYPARAM?

     

    SELECT Sum(Price) as Total
    FROM LineItems
    WHERE AptDate = <cfqueryparam cfsqltype="cf_sql_timestamp" value="#DateAdd('d', i, Now())# />

     

    Should sort all your issues, none of this dates to strings malarkey.

     

    EDIT: Adam's reply in the meantime with same suggestion

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points