Thursday, November 20, 2008

ADO Timeouts: Connection vs. Command vs. RecordSet

The Problem

An interesting bit I learned today is that if you need to extend the time limit for an intensive SQL query or procedure executed using ADO, setting only the commandTimeout property of your ADODB.Connection instance is not sufficient. You will see that you have extended the connection time limit, but queries will still time out within the default limit of 30 seconds.

Example
Using VBScript in ASP 3:
set con = createObject("ADODB.Connection")
con.open connectionString
con.commandTimeout = 60

set command = createObject("ADODB.Command")
command.activeConnection = con
command.commandType = adCmdText
command.commandText = sql
command.execute
response.write command.commandTimeout 'Actually 30 (the default).

The Solution

You must also set the commandTimeout property on the ADODB.Command or ADODB.Recordset being used. Otherwise those objects will use the default time limit of 30 seconds because they do not inherit the time limit from the associated ADODB.Connection instance.

Example
Using VBScript in ASP 3:
set con = createObject("ADODB.Connection")
con.open connectionString
con.commandTimeout = 60

set command = createObject("ADODB.Command")
command.activeConnection = con
command.commandType = adCmdText
command.commandText = sql
command.commandTimeout = 60
command.execute
response.write command.commandTimeout 'This is now 60 seconds.

See this Microsoft Tech Note for more.

Friday, November 14, 2008

AS3 Tween class randomly stops during animation

I gave the new AS3 Tween class a whirl to perform some simple animation entirely via ActionScript, rather than sharing the responsibilities between ActionScript and the Timeline.

It worked great...most of the time. The rest of the time, the Tweens would randomly decide to stop -- mid-animation -- without throwing any error as to why. "Most of the time" just doesn't cut it.

The Problem

Here is a simplified example of this situation:

package
{
   import flash.display.*;
   import fl.transitions.*;
   import fl.transitions.easing.*;

   public class SomeContainer() extends Sprite
   {
      ...
      public function animate(o:DisplayObject, x2:int, duration:uint)
      {
         var tween:Tween = new Tween(
               o,
               "x",
               Regular.easeOut,
               someDisplayObject.x,
               x2),
               duration);

      }
   }
}

When invoking animate(), the tween works most of the time, but randomly it stops.

There is no warning of this problem in the ActionScript 3 reference manual, but this Adobe Devnet article contains some fine print that reads:

Note: Consider variable scope when using the Tween class. If a tween is created in a function, it is important that the variable's scope exists beyond the function itself. If a tween is stored to a variable of local scope, ActionScript garbage collection removes the tween as the function completes, which will likely be before the tween has even begun.

So the problem with this scenario is that the Flash Garbage Collector does not care whether the function-scoped variable is still working asynchronously or not - it destroys objects simply by reference counts and in this case nothing outside of the function references this Tween instance.

The Solution

To fix this, simply scope the Tween instance to a class-level variable (a private attribute) rather than a function-level variable. For example:

package
{
   import flash.display.*;
   import fl.transitions.*;
   import fl.transitions.easing.*;

   public class SomeContainer() extends Sprite
   {
      ...
      public function animate(o:DisplayObject, x2:int, duration:uint)
      {
         tween = new Tween(
               o,
               "x",
               Regular.easeOut,
               someDisplayObject.x,
               x2),
               duration);
      }

      private var tween:Tween;
   }
}

This way, the garbage collector sees that something outside of the scope of the function still references the Tween instance created within the function, so it does not destroy the instance.

Wednesday, November 5, 2008

Installing CS4 - Flash 10!

As if it weren't enough of a treat to find out today that Barack Obama was elected as our 44th US President, my day got even better because Adobe CS4 just arrived at the office! I know there's no comparison here, but being given so much in one day is overwhelming!

I'm looking forward to playing with all of the new features in Flash 10 including the new z-axis for 3d transformations, the bones tool for creating skeleton-based animations, and the object motion editor (ripped from After Effects) to replace somewhat clunky keyframe motion.

And to turn it up another notch (BAM!) a free Zinc 3.0 upgrade to 3.0.11 was released to include Flash 10 SWF support.

Tuesday, November 4, 2008

Inter-database Communication is Easy in T-SQL

Problem

You need to obtain data from one data source to process and store in another. You don't want your server-side-script to use two connection objects and be the slow middle-man between them, as in the diagram on the left.

Slow with two SQL Server connections and scripting vs. Optimal with only one connection.


Solution

If both data sources are databases on the same MS SQL Server, it's a piece of cake to do optimally with just one connection object and pure T-SQL.

Just do the following:
  1. Set up Security - Add the user of the destination database as a user of the source database with at least db_datareader access.

  2. Prefix foreign tables with Schema - In your SQL that writes to the destination-database, prefix all tables housed in the source(foreign)-database with their "fully qualified" position in the schema to indicate which database they reside in, as illustrated in the example below.

    Example
    Table tblSource is from of the ForeignDB database, but tblDestination is from the active database.
    insert into tblDestination (colA, colB)
    select col1, col2
    from [ForeignDB].dbo.tblSource