How to manage many openAsync() calls in a big Flex application? - actionscript-3

I used openAsync() function many times in my application to open SQLite connection with a success. But lately I added more code that also uses openAsync() and now I obtain this error:
Error: Error #3110: Operation cannot be performed while SQLStatement.executing is true.
at Error$/throwError()
at flash.data::SQLStatement/checkReady()
at flash.data::SQLStatement/execute()
at Function/com.lang.SQL:SQLErrorStack/deleteAllRecordsFromErrorStackTable/com.lang.SQL:connOpenHandler()[C:\work\Lang\trunk\actionscript\src\com\lang\SQL\SQLErrorStack.as:466]
It looks like the previous code didn't finish executing while another has started.
My question is: Why the execution of code in the second connection was rejected? I expected that some kind of a queue mechanism is used but it isn't. I looked everywhere for a solution how to cope with this problem but I failed. Can you help?
Can one opened DB connection solve the problem? What changes to my code should I apply then?
This is the code similar to this, that appears a few times in my application.
var SQLquery:String;
SQLquery = "DELETE FROM ErrorStackTable";
var sqlConn:SQLConnection = new SQLConnection();
sqlConn.addEventListener(SQLEvent.OPEN, connOpenHandler);
var dbFile:File = new File();
dbFile.nativePath = FlexGlobals.topLevelApplication.databaseFullPath_conf+"\\"+FlexGlobals.topLevelApplication.databaseName_conf;
sqlConn.openAsync(dbFile); // openDB
sqlSelect = new SQLStatement();
sqlSelect.sqlConnection = sqlConn;
sqlSelect.text = SQLquery;
function connOpenHandler(event:SQLEvent):void
{
sqlSelect.addEventListener(SQLEvent.RESULT, resultSQLHandler);
sqlSelect.addEventListener(SQLErrorEvent.ERROR, errorHandler);
sqlSelect.execute();
}

In Big Flex Applications Try To Avoid openAsync(db) calls because of the reusablity of the SQL code , if u have many sql statments to be executed then you should define more and more sql statments . and if you have dynamic result [Array] getting from web service (RPC ) then you will surely get an error although it is successful Execution and array insertion in the database will be fail .. Just Look at
the link Click Here You Will Get your answer
I just changed conn.openAsync(db); to conn.open(db); and it worked
Thanks

Related

OrmLite (ServiceStack): Only use temporary db-connections (use 'using'?)

For the last 10+ years or so, I have always opened a connection the database (mysql) and kept it open, until the application closed. All queries was executed on the connection.
Now, when I see examples on Servicestack webpage, i always see the using-block being used, like:
using (var db = dbFactory.Open())
{
if (db.CreateTableIfNotExists<Poco>())
{
db.Insert(new Poco { Id = 1, Name = "Seed Data"});
}
var result = db.SingleById<Poco>(1);
result.PrintDump(); //= {Id: 1, Name:Seed Data}
}
In my current test-project, I got OrmLite to work in my normal way (one db-connection, no using-statements), so I basically had a class-wide _db, like this:
_dbFactory = new OrmLiteConnectionFactory($"Uid={dbAccount.Username};Password={dbAccount.Password};Server={dbAccount.Address};Port={dbAccount.Port};Database={dbAccount.Database}", MySqlDialect.Provider);
_db = _dbFactory.Open(); // var kept in memory, and used for all queries
It worked in the beginning, but now I suddenly got the Exception:
There is already an open DataReader associated with this Connection which must be closed first
Some code might run a SELECT here and there, and if I understand it correctly, if a SELECT and an INSERT would occur at the same time, this error appears?
If so, is it best-practice to always open a new connection for every single query (say, inside a using-statement)? Isnt that a big overhead, to do what for every query?
Having 1 DB Connection is not ThreadSafe so holding on to the connection is only an option if there’s at most 1 thread accessing the DB connection.
Most ADO.NET providers enable connection pooling by default so it’s more efficient to close the connection when you’re done with it as the connection gets returned back to the pool which reduces the number of active connections in use.

IndexedDB: When to close a connection

I would like to know what the correct place to close a connection to the database is.
Let's say that I have the following piece of code:
function addItem(dbName, versionNumber, storeName, element, callback){
var requestOpenDB = indexedDB.open(dbName, versionNumber); //IDBRequest
requestOpenDB.onsuccess = function(event){
//console.log ("requestOpenDB.onsuccess ");
var db = event.target.result;
var trans = db.transaction(storeName, "readwrite");
var store = trans.objectStore(storeName);
var requestAdd = store.add(element);
requestAdd.onsuccess = function(event) {
callback("Success");
};
requestAdd.onerror = function(event) {
callback("Error");
};
};
requestOpenDB.onerror = function(event) {
console.log ("Error:" + event.srcElement.error.message);/* handle error */
callback("Error");
};
}
addItem basically adds a new element into the database. As per my understanding, when the requestAdd event is triggered that doesn't mean necessarily that the transaction has finished. Therefore I am wondering what the best place to call db.close() is. I was closing the connection inside of requestAdd.onsucess, but if an error happens and requestAdd.onerror is triggered instead, the connection might still be opened. I am thinking about adding trans.oncomplete just under request.onerror and close the db connection here which might be a better option. Any inputs will be more than welcome. Thank you.
You may wish to explicitly close a connection if you anticipate upgrading your database schema. Here's the scenario:
A user opens your site in one tab (tab #1), and leaves it open.
You push an update to your site, which includes code to upgrade the database schema, increasing the version number.
The same user opens a second tab to your site (tab #2) and it attempts to connect to the database.
If the connection is held open by tab #1, the connection/upgrade attempt by tab #2 will be blocked. Tab #1 will see a "versionchange" event (so it could close on demand); if it doesn't close its connection then tab #2 will see a "blocked" event.
If the connection is not held open by tab #1, then tab #2 will be able to connect and upgrade. If tab #1 then tries (based on user action, etc) to open the database (with an explicit version number) it will fail since it will be using an old version number (since it still has the old code).
You generally never need to close a connection. You are not creating memory leaks or anything like that. Leaving the connection open does not result in a material performance hit.
I would suggest not worrying about it.
Also, whether you add trans.oncomplete before or after request.onerror is not important. I understand how it can be confusing, but the order in which you bind the listeners is irrelevant (qualified: from within the same function scope).
You can call db.close() immediately after creating the transaction
var trans = db.transaction(storeName, "readwrite");
db.close();
and it will close the connection only after the transaction has completed.
https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/close says
The connection is not actually closed until all transactions created using this connection are complete. No new transactions can be created for this connection once this method is called.
If you want to run multiple versions of your app and both access the same database, you might think it's possible to keep connections open to both. This is not possible. You must close the database on one before opening it on another. But one problem is that there is currently no way to know when the database actually closes.

Flex database getting overwritten

I am maintaining an existing flex desktop application which is using SQLite3 database. I am very new to Flex programming.
The database originally has some test values which I changed by deleting the existing table importing the new data with same table name.
Now once I run the application, I still see old data, and on checking the database table find test values back there and new values gone.
I checked the code for any insert or import statement but could not locate one. Does any one faced similar issue? Is it because database cacheing, if yes then how to clear this cache? Any hint on what could be the reason behind this weird issue?
Flex creates a location to save data locally in machine. In my machine the path is under my userid AppData\Roaming\ProjectName\Local Store\Database\dbname.db
And my code responsible is following (Line 9, dbWorkFile variable):
public function SQLCon(strQuery:String):SQLResult
{
try
{
var dbStatement:SQLStatement = new SQLStatement();
var dbFile:File = File.applicationDirectory.resolvePath("DataBase/question.db"); //file in the compiled folder
var dbWorkFile:File = File.applicationStorageDirectory.resolvePath("DataBase/question.db");//Location of roaming database
if(!dbWorkFile.exists){
dbFile.copyTo(dbWorkFile);
}
conn = new SQLConnection();
conn.open(dbWorkFile);
....
Leaving this answer for benefit of someone who faces similar ghost issue :)

Send an integer into a server with GET method

I've been researching this problem for a while now and have been trying to use the POST method until recently when I figured out that the GET method will be sufficient for what I need to do.
My objective:
Take an integer from my app and send it into a php server to save it
For now, I just need to send one integer to get it working and to have a starting point to work from. Once I start getting the ball rolling and things start working, I will be sending maybe 20 integers maximum at a time, so I don't believe that I will have a problem with the data amount restrictions on the GET method.
I am working with a friend on this project right now because I am not as fluent in php, I have been exposed to it several times though, so I should know most of the terminology involved. ANYWAY, here is my php code that my friend wrote for me...
<?php
// A sample php file to demo passing parameters and getting POST data.
// This simply appends the specified value to the end of the 'sample' table.
// Call it like this: sample.php?val=4
// where 4 is the value you want to append to the table
// The code returns whether or not the sql query was performed with success or not.
// If successful, a boolean true (or 1) is returned.
// If not, then an error message is returned with the sql error.
include 'dbConnect.php';
$val = $_GET["val"]; // value to set to
$sql=
"INSERT INTO sample (`test`)
VALUES ('" . $val . "')
";
$result = mysql_query($sql,$con);
if(!$result){
die('Error: ' . mysql_error());
}
echo $val+1;
mysql_close($con);
?>
This code takes the sent value for the variable "val" and echoes that value plus one (so that the setting and the getting values are different from the site so I can more easily tell if my code works) This should work right?
Next, I believe I haven't quite finished the Xcode portion of the project yet, but I have a successful connection happening, I just haven't been able to change the value of the variable in the php server. In my project, I have an NSInteger variable called "num" and its value, set by the text field in my app, is the one I want to send in to the server. I also am using a button (called "postPressed") to initiate the function of the sending process. So here is my code...
NSURLRequest *request;
NSURLConnection *connection;
NSURL *url;
NSInteger num;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (IBAction)valueChange:(id)sender {
num = [_valueTF.text intValue];
}
- (IBAction)postPressed:(id)sender {
url = [NSURL URLWithString: [NSString stringWithFormat: #"http://jrl.teamdriven.us/source/scripts/2013/sample.php?val=%d", num]];
request = [NSURLRequest requestWithURL:url];
if (request) {
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
_returnLbl.text = #"success!";
}
}
My returnLbl does change to be "success", so I know the connection works, I just think I'm missing some code on the setting the variable part. Please help me out, this has been a thorn in my side for about a month now. Also, I apologize for the length of this question, I'm just trying to get in all the details so that there doesn't have to be any clarifications.
So, it turns out that my code worked the whole time, it's just that when I looked up the data table generated by phpMyAdmin, I did not happen to notice that there was a page two of data because I had tested it so much in my browser. The integers were sent and saved successfully with the code above. I apologize for posting something like this and finding out how dumb of a mistake it truly was, but if anyone would like to give me any kinds of improvements, I am open to them. Thank you for taking your time to view this question.

Coldfuson CFScript "setSQL" method was not found

I've got a Coldfusion component, with a method in it called getColumnNames
This just queries a MySQL table, and returns the columnlist:
remote string function getColumnNames() {
qProcessCars = new Query();
qProcessCars.setDataSource('#APPLICATION.dsn#');
qProcessCars.setSQL('SELECT * FROM sand_cars WHERE 1 LIMIT 1');
qProcessCars = qProcessCars.Execute().getResult();
return qProcessCars.columnlist;
}
If I access this remotely in the browser, with page.cfc?method=getColumnNames, then I get the expected list of columns back.
However, if I try to access this from inside another method within the component, I get an error
remote string function otherFunction() {
...
sColumns = getColumnNames();
...
}
The error dump for the above code returns the message "The setSQL method was not found".
So can anyone help me find out why it works as a remote call, but not when called from another method inside the same component.
Problem may be caused some kind of race conditions. If you make few calls which interfere, at some point qProcessCars may already be query result, so invoking method is not possible.
I would try to make the qProcessCars variable local scoped (var qProcessCars = new Query();
) and/or try to use another variable name for query results.
Next possible step is to enclose the query building/executing code into named lock.
Ah I've answered my own question again. Sorry.
I've used the same name qProcessCars else where in the component, I hadn't put var in front of them.
I don't know WHY that was causing the problem, but it was. Maybe setSQL can only be called once per query object?