Category Archives: Rant

A rant is a speech or text that does not present a well-researched and calm argument; rather, it is typically an attack on an idea, a person or an institution. Very often rants lack proven claims. Such attacks are usually personal attacks. Compare with a dialectic. – Wikipedia

Using and working with IndexedDB

Below is a sample example code for IndexedDB

//nsr is namespace
(function (nsr, $, undefined) {
    //private variables
    nsr.myTvQ.indexedDB = nsr.myTvQ.indexedDB || {};
    nsr.myTvQ.indexedDB.db = null;
    nsr.myTvQ.indexedDB.version = "1.0";
    
    //saving webkitIndexedDB in global namespace
    if ('webkitIndexedDB' in window) {
        window.indexedDB = window.webkitIndexedDB;
        window.IDBTransaction = window.webkitIDBTransaction;
        window.IDBKeyRange = window.webkitIDBKeyRange;
        window.IDBCursor = window.webkitIDBCursor;
    }
    //global error handler
    nsr.myTvQ.indexedDB.onerror = function (e) {
        console.log("myError: ", e);        
    };
    // callback param in integer, -1 error, 0 exiting, 1 new
    nsr.myTvQ.indexedDB.Open = function (callback) {
        if (nsr.myTvQ.indexedDB.db) {
            if (callback) {
                callback(0);//opened but present
            }
            return;
        }
        var request = indexedDB.open("myTvQDB", "comments bla blah database v1.0");

        request.onsuccess = function (e) {
            var v = nsr.myTvQ.indexedDB.version;
            nsr.myTvQ.indexedDB.db = e.target.result;
            var db = nsr.myTvQ.indexedDB.db;
            console.log('opened indexedDB myTvQDB v:' + db.version);            

            // We can only create Object stores in a setVersion transaction;
            // so if version not found update or create new db
            if (v != db.version) {
                console.log('setting new v ',v, db.version);
                var setVrequest = db.setVersion(v);

                // onsuccess is the only place we can create Object Stores
                setVrequest.onfailure = request.onfailure =  function (e) 
                {        
                    console.log("myError: ", e); 
                    if (callback) {                        
                        callback(-1);
                    }
                };
                setVrequest.onsuccess = function (e) {
                    //create this at last, since update_time is stored in end
                    nsr.myTvQ.indexedDB.DropObjectStore("settings");
                    nsr.myTvQ.indexedDB.CreateSettingsStore();

                    nsr.myTvQ.indexedDB.DropObjectStore("listings");
                    nsr.myTvQ.indexedDB.listing.CreateListingsStore();         
                    if (callback) {
                        callback(1);//created                        
                    }
                };
            } else {
                if (callback) {
                    callback(0);//opened but present
                }
                console.log('object stores are present');
            }
        };

        request.onfailure =  function (e) 
        {        
            console.log("myError: ", e); 
            if (callback) {
                callback(-1);//error
            }
        };
    }
    
    //helper methods
    nsr.myTvQ.indexedDB.Close = function(){
        try {
            var db = nsr.myTvQ.indexedDB.db;
            if (db) {
                db.close();
                nsr.myTvQ.indexedDB.db = null;
                if (callback) {
                    callback(1);
                }
            }   
        } catch (ex) {
            if (callback) {
                callback(-1);
            }
            console.log("Exception in Close() - " + ex.message);
        }
    } 
    nsr.myTvQ.indexedDB.DeleteDatabase = function(callback){
        try {
            var db = nsr.myTvQ.indexedDB.db;
            if (db) {
                db.close();
            }   
            var request =  window.indexedDB.deleteDatabase('myTvQDB');
            request.onsuccess = function (e) {
                nsr.myTvQ.indexedDB.db = null;
                if (callback) {
                    callback(1);
                }
                console.log('Database successfully deleted');
            };
            request.onfailure = function (e) 
            {        
                console.log("myError: ", e); 
                if (callback) {
                    callback(-1);
                }
            };    
        } catch (ex) {
            if (callback) {
                callback(-1);
            }
            console.log("Exception in DeleteDatabase() - " + ex.message);
        }
    }
    
    nsr.myTvQ.indexedDB.DropObjectStore = function (storeName) {
        var db = nsr.myTvQ.indexedDB.db;
        if (db.objectStoreNames.contains(storeName)) {
            db.deleteObjectStore(storeName);
            console.log('objectstore ' + storeName + ' dropped');
        }
    }

    nsr.myTvQ.indexedDB.ForceDropObjectStore = function (storeName) {
        var db = nsr.myTvQ.indexedDB.db;
        var setVrequest = db.setVersion(Math.random());
        setVrequest.onfailure = nsr.myTvQ.indexedDB.onerror;
        setVrequest.onsuccess = function (e) {
            console.log('db.version ', db.version);
            nsr.myTvQ.indexedDB.DropObjectStore(storeName);
        }
    };
    
    //can use to re-create empty ObjectStore
    nsr.myTvQ.indexedDB.ForceCreateObjectStore = function (storeName) {
        console.log('ForceCreateObjectStore', storeName);
        var db = nsr.myTvQ.indexedDB.db;
        var setVrequest = db.setVersion(Math.random());
        setVrequest.onfailure = nsr.myTvQ.indexedDB.onerror;
        setVrequest.onsuccess = function (e) {
            console.log('db.version ', db.version);
            nsr.myTvQ.indexedDB.DropObjectStore(storeName);
            switch(storeName){
                case "listings":
                    nsr.myTvQ.indexedDB.listing.CreateListingsStore();
                    break;	
                case "settings":
                    nsr.myTvQ.indexedDB.listing.CreateSettingsStore();
                    break;	   
                default:
                    break;
                }
            nsr.myTvQ.indexedDB.ResetVersion();
        }
    };
    
    //set version back to old version
    nsr.myTvQ.indexedDB.ResetVersion = function () {
        var db = nsr.myTvQ.indexedDB.db;
        var setVrequest = db.setVersion(nsr.myTvQ.indexedDB.version);
        setVrequest.onfailure = nsr.myTvQ.indexedDB.onerror;
        setVrequest.onsuccess = function (e) {
            console.log('reset db.version ', db.version);
        }
    };
    
    //empty or truncate table
    nsr.myTvQ.indexedDB.ClearAll = function(storeName, callback){
        var db = nsr.myTvQ.indexedDB.db;
        if (db.objectStoreNames.contains(storeName)) {
            var clearTransaction = db.transaction([storeName], IDBTransaction.READ_WRITE);
            var clearRequest = clearTransaction.objectStore(storeName).clear();
            clearRequest.onsuccess = function(event){
                 //event.target.result contains undefined
                 if (callback) {
                    callback(true);
                 }                 
            };
            clearRequest.onerror = function(event){            
                 console.log("myError: ", event);
                 if (callback) {
                    callback(false);
                 }                                  
            };
        }else {
            console.log(storeName+ " doesnot exist ");
            if (callback) {
                    callback(false);
            }                 
        }
    }
    //nsr.myTvQ.indexedDB.ListAll('','store_id',function(l1){console.log(l1);});
    nsr.myTvQ.indexedDB.ListAll = function(storeName, objOrArray, callback){
        var db = nsr.myTvQ.indexedDB.db;
        if (db.objectStoreNames.contains(storeName)) {
            var transaction = db.transaction(storeName, IDBTransaction.READ_ONLY);
            var list = objOrArray ? {} : [] ;
            transaction.oncomplete = function(event) {
                if(callback){
                    //console.log(results);
                    callback(list);
                }
            };
            transaction.onerror = nsr.myTvQ.indexedDB.onerror;
            var cursorRequest = transaction.objectStore(storeName).openCursor();
            
            cursorRequest.onsuccess = function(ev) {
                var cursor = cursorRequest.result || ev.target.result;
                if(!!cursor == false)
                    return;
                if(objOrArray){
                    list[cursor.value[objOrArray]] = cursor.value;
                }
                else{
                    list.push(cursor.value);                
                }
                cursor.continue();
            };      
        }else {
            console.log(storeName+ " doesnot exist ");
            if (callback) {
                    callback(false);
            }                 
        }            
    }
    
    nsr.myTvQ.indexedDB.Delete = function(storeName, key, callback){
        var db = nsr.myTvQ.indexedDB.db;
        var request = db.transaction(storeName, IDBTransaction.READ_WRITE)  
                .objectStore(storeName)  
                .delete(key);  
        request.onsuccess = function(event) {  
          if(callback){
                //console.log(results);
                callback(true);
            }  
        };
        request.onerror = function(event) {  
          if(callback){
                callback(false);
            }  
        };
    }
    
    nsr.myTvQ.indexedDB.CreateSettingsStore = function(callback){
        var db = nsr.myTvQ.indexedDB.db;
        if(!db.objectStoreNames.contains("settings")) {
            //will be used by background to get all past dates and run operations on them
            db.createObjectStore("settings",{keyPath:"Name"});
            console.log('objectstore settings created');
                        
            nsr.myTvQ.indexedDB.SetAllSettings(undefined,callback);
        }
    };
    
    
    
    nsr.myTvQ.indexedDB.GetAllSettings = function(callback){
        var db = nsr.myTvQ.indexedDB.db;        
        var settings = {};
        var transaction = db.transaction(["settings"], IDBTransaction.READ_ONLY);
        transaction.oncomplete = function(event) {  
          if(callback){
            callback(settings);
          }
        }; 
        transaction.onerror = nsr.myTvQ.indexedDB.onerror;
        var store = transaction.objectStore("settings");
        var cursorRequest = store.openCursor(IDBKeyRange.lowerBound(0));
        cursorRequest.onsuccess = function(ev) {
            var cursor = cursorRequest.result || ev.target.result;
            if(!!cursor == false)
                return;
            //console.log(cursor.value);
            settings[cursor.value.Name] = cursor.value.Value;
            cursor.continue();
        };          
    }

    nsr.myTvQ.indexedDB.SetAllSettings = function(settings, callback){
         var db = nsr.myTvQ.indexedDB.db; 
         var transaction = db.transaction(["settings"], IDBTransaction.READ_WRITE);
         var store = transaction.objectStore("settings");
         transaction.oncomplete = function(event) {  
            if(callback){
                console.log('SetAllSettings Initialized');
                callback();
            }
         }; 
         transaction.onerror = nsr.myTvQ.indexedDB.onerror;
         settings = settings || {};
         var init_list = [{"Name":"update_time","Value":settings.update_time || (new Date()).getTime() }                          
                            ,{"Name":"enable_notification","Value":settings.enable_notification || 1}
                            ,{"Name":"default_country","Value":settings.default_country || 'US'}];

         $.each(init_list, function (index0, item0) {
                var request = store.put(item0);
                request.onsuccess = function(event) {};
                request.onerror = function(event) {
                    console.log(event);
                }; 
         });
    }

    nsr.myTvQ.indexedDB.GetSettingsFor = function(name, callback){
        var db = nsr.myTvQ.indexedDB.db;
        var resultset = null;
        var transaction = db.transaction(["settings"], IDBTransaction.READ_ONLY);
        transaction.oncomplete = function(event) {  
          if(callback){
            callback(resultset);
          }
        }; 
        transaction.onerror = nsr.myTvQ.indexedDB.onerror;
        var store = transaction.objectStore("settings");
        var request = store.get(name);  
        request.onerror = function(event) {  
          console.log(event);
        };  
        request.onsuccess = function(event) {  
          resultset = request.result ? request.result.Value : undefined ;  
        };
    }

    nsr.myTvQ.indexedDB.SetSettingsFor = function(name, value, callback){
        var db = nsr.myTvQ.indexedDB.db;
        var transaction = db.transaction(["settings"], IDBTransaction.READ_WRITE);
        transaction.oncomplete = function(event) {  
          if(callback){
            callback(true);
          }
        }; 
        transaction.onerror = function(event) {  
          if(callback){
            callback(false);
          }
        }; 
        var store = transaction.objectStore("settings");
        var request = store.put({"Name":name,"Value":value});  
        request.onerror = function(event) {  
          console.log(event);
        };  
        request.onsuccess = function(event) {};
    }    
    
    ///Show Listings
    nsr.myTvQ.indexedDB.listing.CreateListingsStore = function(callback){
        var db = nsr.myTvQ.indexedDB.db;
        if(!db.objectStoreNames.contains("listings")) {
            var store = db.createObjectStore("listings", { keyPath: "show_id" });
            store.createIndex("countryIndex", "country", { unique: false });
            store.createIndex("country_statusIndex", "country_status", { unique: false });
            store.createIndex("show_name_Index", "show_name", { unique: false });
            console.log('objectstore listing created');  
            if(callback){
                callback(true);
            }          
        }else {
            if(callback){
                console.log('CreateListingsStore already exits');
                callback(true);
            }
        }
    };
    
    nsr.myTvQ.indexedDB.listing.AddListings = function (x2j_list_new, index, callback) {
        //no need to clear, since its add or update.        
        var db = nsr.myTvQ.indexedDB.db;
        var transaction = db.transaction(["listings"], IDBTransaction.READ_WRITE);
        var count = 0;
        transaction.oncomplete = function (event) {
            if (callback) {
                console.log('x2jShowListing Added ' + count + '/' + x2j_list_new.length);
                callback([index, count, x2j_list_new.length]);
            }
        };
        transaction.onerror = nsr.myTvQ.indexedDB.onerror;
        var store = transaction.objectStore("listings");
        console.log('AddListings looping'+index);
        $.each(x2j_list_new, function (index0, item0) {
            var request = store.put(item0);
            request.onsuccess = function (event) {
                count++;
                // event.target.result == show_id  
            };
        });        
    };

    nsr.myTvQ.listing.AddListingsInChunks = function (progressElemId, callback) {
        $(progressElemId).html('(Listing is older than 14 days, fetching latest from server)');
        nsr.myTvQ.listing.GetListingsFromTvRage(function (x2j_list_new) {
            if (!x2j_list_new) {
                if (callback) {
                    $(progressElemId).html('(Encountered Error while fetching, please try again later.)');
                    callback(false);
                    return;
                }
            }
            console.log('x2j_list_new now calling AddListings');
            
            //http://stackoverflow.com/questions/8495687/split-array-into-chunks      
            var i = 0, j = x2j_list_new.length, temp_array, chunk = 500;
            $(progressElemId).html('(Got a total of '+j+' Shows)');
            //http://www.kryogenix.org/days/2009/07/03/not-blocking-the-ui-in-tight-javascript-loops
            function doWork() {
                temp_array = x2j_list_new.slice(i, i + chunk);
                nsr.myTvQ.indexedDB.listing.AddListings(temp_array, i, function (cnt) {
                    if (cnt[0] >= j - chunk) {
                        console.log('AddListings ALL DONE', cnt);
                        if (callback) {
                            $(progressElemId).html('(Saving Shows locally 100% Comlepete. Now generating screen. Almost there... )');
                            callback(true);
                            return;
                        }
                    }
                    $(progressElemId).html('(Saving '+j+' Shows locally, '+(((i + chunk >=j ? j: i + chunk)/j)*100).toFixed(2) +'% Done.)');
                    console.log(cnt);
                });
                i += chunk;
                if (i < j) {
                    setTimeout(doWork, 100);
                }
            };
            setTimeout(doWork, 100);            
        });
    } 
    
    nsr.myTvQ.indexedDB.listing.GetAllCountries = function (callback) {
        var db = nsr.myTvQ.indexedDB.db;
        var resultset = [];
        var transaction = db.transaction(["listings"], IDBTransaction.READ_ONLY);
        transaction.oncomplete = function(event) {  
          if(callback){
            callback(resultset);
          }
        }; 
        transaction.onerror = nsr.myTvQ.indexedDB.onerror;
        var store = transaction.objectStore("listings");

        var countryIndex = store.index("countryIndex");
        
        var cursorRequest = countryIndex.openKeyCursor(null, IDBCursor.NEXT_NO_DUPLICATE);
        cursorRequest.onsuccess = function(ev) {
          var cursor = cursorRequest.result;
          if (cursor) {
            resultset.push(cursor.key);
            //console.log(cursor.value);//undefined
            cursor.continue();
          }
        };
    };    

    nsr.myTvQ.indexedDB.listing.GetListingByCountry = function (country, callback) {
        console.log("GetListingBy country");
        var resultset = [];
        var db = nsr.myTvQ.indexedDB.db;
        var transaction = db.transaction(["listings"], IDBTransaction.READ_ONLY);
        transaction.oncomplete = function(event) {  
            if(callback){
            callback(resultset);
            }
        }; 
        transaction.onerror = nsr.myTvQ.indexedDB.onerror;
        var store = transaction.objectStore("listings");

        var countryIndex = store.index("countryIndex");
            
        var cursorRequest = countryIndex.openCursor(new IDBKeyRange.only(country));
        cursorRequest.onsuccess = function(ev) {
            var cursor = cursorRequest.result;
            if (cursor) {
            resultset.push(cursor.value);
                
            cursor.continue();
            }
        };
    };

    nsr.myTvQ.indexedDB.listing.GetListingByCountryStatus = function (country, status, callback) {
        var resultset = [];
        var db = nsr.myTvQ.indexedDB.db;
        var transaction = db.transaction(["listings"], IDBTransaction.READ_ONLY);
        transaction.oncomplete = function(event) {  
          if(callback){
            callback(resultset);
          }
        }; 
        transaction.onerror = nsr.myTvQ.indexedDB.onerror;
        var store = transaction.objectStore("listings");

        var country_statusIndex = store.index("country_statusIndex");
        var cursorRequest = country_statusIndex.openCursor(new IDBKeyRange.only(country +'_'+ status));
        cursorRequest.onsuccess = function(ev) {
          var cursor = cursorRequest.result;
          if (cursor) {
            resultset.push(cursor.value);
            //console.log(cursor.value);
            cursor.continue();
          }          
        };
    };
    
    //from ="A", to="B"
    nsr.myTvQ.indexedDB.listing.GetCountryByRange = function (from, to) {
        var db = nsr.myTvQ.indexedDB.db;
        var resultset = [];
        var transaction = db.transaction(["listings"], IDBTransaction.READ_ONLY);
        transaction.oncomplete = function(event) {  
            console.log(resultset);
        }; 
        transaction.onerror = nsr.myTvQ.indexedDB.onerror;
        var store = transaction.objectStore("listings");

        var countryIndex = store.index("countryIndex");
        
        var cursorRequest = countryIndex.openKeyCursor(IDBKeyRange.bound(from,to,false,true), IDBCursor.NEXT_NO_DUPLICATE);
        cursorRequest.onsuccess = function(ev) {
          var cursor = cursorRequest.result;
          if (cursor) {
            resultset.push(cursor.key);
            //console.log(cursor.value);//undefined
            cursor.continue();
          }
        };
    };
    
    //chrome doesnot support count yet.
    nsr.myTvQ.indexedDB.listing.CountListing = function (callback) {        
        var db = nsr.myTvQ.indexedDB.db;
        var transaction = db.transaction(["listings"], IDBTransaction.READ_ONLY);
        var count = 0;
        transaction.oncomplete = function(event) {  
          if(callback){
            callback(count);
          }
        };
        transaction.onerror = nsr.myTvQ.indexedDB.onerror;
        var store = transaction.objectStore("listings");

        var keyRange = IDBKeyRange.lowerBound(0);
        var showidRequest  = store.openCursor(keyRange);
        showidRequest.onsuccess = function(ev) {
          var result = ev.target.result;
          if(!!result == false)
            return;
                      
            count++;
            result.continue();          
        };
    }

    nsr.myTvQ.indexedDB.listing.CountListingBy = function (country, callback) {        
        var db = nsr.myTvQ.indexedDB.db;
        var transaction = db.transaction(["listings"], IDBTransaction.READ_ONLY);
        var count=0;
        transaction.oncomplete = function(event) {  
          if(callback){
            //console.log(count);
            callback(count);
          }
        };
        transaction.onerror = nsr.myTvQ.indexedDB.onerror;
        var store = transaction.objectStore("listings");

        var countryIndex = store.index("countryIndex");
        
        var cursorRequest = countryIndex.openCursor(new IDBKeyRange.only(country));
        cursorRequest.onsuccess = function(ev) {
          var cursor = cursorRequest.result;
          if(!!cursor == false)
            return;

          count++;
          cursor.continue();
        };        
    }                           

} (window.nsr = window.nsr || {}, jQuery));

Convert xml to json or JavaScript object

For my Google chrome extension TV WatchList, I needed to save TVRage.com’s xml feed in indexedDB. Since it only takes json object,I decided to make a small library which can convert xml to¬†JavaScript¬†xml2json. Existing solutions did not work for me due various reasons like node with url was giving me blank values, console.log would throw circular exeptions during debugging, and couple of other things i dont remember right now.

This library is 100% javascript with no third party library dependency.
Also This is only tested in chrome browser.This should work in other browsers too (maybe with minor tweaks)
Anyway lets start with some code

Sample XML – shows.xml

<?xml version="1.0" encoding="UTF-8" ?>
<Results>
    <show>
        <name>One Piece (JP)</name>
        <link>http://www.tvrage.com/One_Piece_JP</link>
        <country>JP</country>
        <started>Oct/20/1999</started>
        <ended></ended>
        <genres><genre>Anime</genre><genre>Action</genre><genre>Adventure</genre><genre>Comedy</genre><genre>Fantasy</genre></genres>
        <network country="JP">Fuji TV</network>
        <akas><aka country="JP">&#12527;&#12531;&#12500;&#12540;&#12473;</aka></akas>
    </show>
    <show>
        <name>One Piece (US)</name>
        <link>http://www.tvrage.com/One_Piece_US</link>
        <country>AJ</country>
        <started>Sep/18/2004</started>
        <ended>Mar/15/2008</ended>
        <genres><genre>Anime</genre><genre>Children</genre></genres>
        <network country="US">Cartoon Network</network>
    </show>
</Results>

Usage:

    var x2jObj = null;
    $.get('shows.xml', function (xmlDocument) {
        x2jObj = X2J.parseXml(xmlDocument); //X2J.parseXml(xmlDocument, '/');
        //x2jObj is called jNode
        console.log('x2jObj populated', x2jObj);
        //...
    });

Read More

VisualSVN pre-commit hook

1.Start VisualSVN Server Manager
2.Under Repositories, Select your repository and then Open Properties
3.Select Hooks tab
4.double click the pre-commit hook

Edit: As of VisualSVN version 2.5 use below code

setlocal enabledelayedexpansion

set REPOS=%1
set TXN=%2

set SVNLOOK="%VISUALSVN_SERVER%\bin\svnlook.exe"

SET M=

REM Concatenate all the lines in the commit message
FOR /F "usebackq delims==" %%g IN (`%SVNLOOK% log -t %TXN% %REPOS%`) DO SET M=!M!%%g

REM Make sure M is defined
SET M=0%M%

REM Here the 6 is the length we require
IF NOT "%M:~6,1%"=="" goto NORMAL_EXIT

:ERROR_TOO_SHORT
echo "Commit note must be at least 6 letters" >&2
goto ERROR_EXIT

:ERROR_EXIT
exit /b 1

REM All checks passed, so allow the commit.
:NORMAL_EXIT
exit 0

If using VisualSVN < 2.5

setlocal

set REPOS=%1
set TXN=%2

set SVNLOOK=”C:\Program Files\VisualSVN Server\bin\svnlook.exe”

REM Make sure that the log message contains some text.
FOR /F “usebackq delims==” %%g IN (`%SVNLOOK% log -t %TXN% %REPOS% FINDSTR /R /C:……`) DO goto NORMAL_EXIT

:ERROR_TOO_SHORT
echo “Comment must be at least 6 letters” >&2
goto ERROR_EXIT

:ERROR_EXIT
exit /b 1

REM All checks passed, so allow the commit.
:NORMAL_EXIT
exit 0

The above code will make the comment of at least 6 letters mandatory.

My Experience with SQL Azure

We are in the process of developing a prototype for Windows Azure.
Since its a fairly a new technology not many online help/discussions
are available. and if there are, then they are obsolete (as these steps would become in couple of months)
the reason being, Microsoft comes out with updates for major/minor versions pretty quickly.
Anyway these are the challenges we faced until now and maybe would face some more in future. Most of them are
due to our ignorance or lack of knowledge on how it could be done in a certain way (thats one more problem with new tech, where
nobody knows what`s the standard way until you make errors).
Now Azure requires latest and greatest. Hence, we decided to use virtual machine to make Win 7 images and install azure sdk
and sql server 2008 (big mistake for sql server…as we painfully found out later that we needed SQL server 2008 R2 CTP!).
So during R&D, we realized that we could use Windows Azure with Storage as our backend. But, it turned out to be a
Hash Table, which is only used to save key value pair, where value can be anything from blob to complex objects etc. However again, we needed a RDBMS. On further research, we found a service called SQL Azure which was exactly what we required for Storage.
And now when we tried to open it with Management Studio, we could only do scripts and not objects.. Bummer!! I am more
used to the GUI aspect of sqlserver then scripts, which made us search for different alternatives in codeplex i.e.
http://hanssens.org/tools/sqlazuremanager/ which were all buggy or mostly incomplete! Turns out we had to install
SQL server 2008 R2 CTP. sigh!!! Who knew??
Once everything was set, we now had to move our existing data from oracle to Azure. We used Microsoft’s tool to migrate data, which was slow but worked fine. Finally, it was a success…Yippee!!

Simple OS A designers dream, a programmers pride

I would like an Operating System which is open source.
Which has two options when its started for the first time.(Basic, Advanced)
Basic:my mother can use.Advanced: something a hardcore programmer hacker can use
which behaves like iPhoneOS/android i.e desktop with icons only(apps)/ no tray or task bar or menus or right clicks
apps can do what ever they want.
everything set to optimal default, plug and play, like boxee, xbmc (even they are a little complicated/clunky)
A single place to store documents,music,videos,settings,app store (with repository can use windows,linux apps).
A Closed App Ecosystem (only through repos like cydia)
no need of c drive,program files.

should have good games and social apps to appeal masses
In short, i want everything which iPad has and also the things it lacks.(multitasking,flash,plugins etc)
I guess future ChromeOS would be pretty close to what i want. There is also Jolicloud