sql - AIR Sqlite: SQLEvent.RESULT not firing, but statement IS executing properly -


ok looks likes have stumbled upon strange timing issue... made quick sql wrapper class executing sql statements. after .execute() called, sqlevent.result event never fired, new entry in db created should be. really odd part if put settimeout() after calling execute() event fires expected.. hope i'm missing obvious here... here link example air app: http://www.massivepoint.com/airsqltest/airsql.zip

and here code wrapper class:

if down @ line 51 in sqlrequest class, see commented out settimeout() method. make work, uncomment line.. me doesn't make sense...

anyone have thoughts? i'm totally stumped here...

package com.jac.sqlite  {//package  import flash.data.sqlconnection;  import flash.data.sqlstatement;  import flash.events.eventdispatcher;  import flash.events.sqlerrorevent;  import flash.events.sqlevent;  import flash.utils.settimeout;   public class sqlrequest extends eventdispatcher  {//sqlrequest class    private var _callback:function;   private var _dbconn:sqlconnection;   private var _query:string;   private var _params:object;    private var _statement:sqlstatement;     public function sqlrequest(callback:function, connection:sqlconnection, query:string, parameters:object=null):void    {//sqlrequest    trace("creating new sql request");    _callback = callback;    _dbconn = connection;    _query = query;    _params = parameters;      _statement = new sqlstatement();    _statement.sqlconnection = _dbconn;    _statement.text = _query;     if (_params != null)    {//assign     (var param:string in _params)     {//params      trace("setting param: " + param + " to: " + _params[param]);      _statement.parameters[param] = _params[param];     }//params    }//assign     //setup events    _statement.addeventlistener(sqlevent.result, handleresult, false, 0, true);    _statement.addeventlistener(sqlerrorevent.error, handleerror, false, 0, true);   }//sqlrequest    public function startload():void   {//execute    _statement.execute();    //settimeout(handletimeout, 10000);   }//execute    //temp   private function handletimeout():void   {//handletimeout    trace("executing: " + _statement.executing + " / " + executing);   }//handletimeout    private function handleresult(e:sqlevent):void    {//handleresult    trace("good sql request");    _callback(e);    dispatchevent(e);   }//handleresult    private function handleerror(e:sqlerrorevent):void    {//handleerror    trace("sql error: " + e.errorid + ": " + e.error);    //dispatchevent(e);   }//handleerror    public function executing():boolean   {//get executing    return _statement.executing;   }//get executing    public function query():string { return _query; }   public function statement():sqlstatement { return _statement; }   }//sqlrequest class  }//package 

i think you're missing here garbage collection.

haven't tested code, source of problem.

var sqlreq:sqlrequest = new sqlrequest(handleresult, _dbconn, sql); sqlreq.startload(); 

the reference sqlreq local function , becomes unreacheable when function returns. makes collectable. guess there must code in air runtime collects garbage more agressively when there sql connections involved. because generally, you'll away not storing ref object (at least in web based environment, in experience; bug in such code, nevertheless; have in bad day experience it).

the settimeout masks problem (or solves it, although in unintended way), because settimeout function uses timer internally. running timers not collected. so, timer alive , kicking , has reference sqlrequest instance, makes reacheable, , so, not elligible collection. if db call takes longer timeout though, you're in same situation.

to solve this, store ref object , dispose when you're done.

edit

another option, if don't want change way calling code works, storing ref instance in class-scoped (i.e. static) dictionary duration of call (this dictionary shoul not use weak referenced keys obvious reasons).

you adding hidden side effect method, not sign of design in general, long remove when call db finished (whether succeded or not), you're safe, think problem more of style else.

what mean this:

private static var _dict:dictionary = new dictionary();  public function startload():void {//execute     _statement.execute();     //  add self reference dict instance won't collected     //  in last line, if have exception in execute,     //  code not run (or add try/catch if want, simpler     //  , cleaner, imo     addtodict(); }//execute  private function handleresult(e:sqlevent):void  {//handleresult     //  remove self reference before running other code     //  (again, in case code follows throws)     removefromdict();     trace("good sql request");     _callback(e);     dispatchevent(e); }//handleresult  private function handleerror(e:sqlerrorevent):void  {//handleerror     //  same comment handleresult     removefromdict();     trace("sql error: " + e.errorid + ": " + e.error);     //dispatchevent(e); }//handleerror  private function addtodict():void {     _dict[this] = true; }  private function removefromdict():void {     if(_dict[this]) {         delete _dict[this];     } } 

Comments

Popular posts from this blog

c++ - How do I get a multi line tooltip in MFC -

asp.net - In javascript how to find the height and width -

c# - DataTable to EnumerableRowCollection -