/// <summary>
        /// Opens the connection using the parameters found in the <see cref="ConnectionString">ConnectionString</see>
        /// </summary>
        public override void Open()
        {
            if (_connectionState != ConnectionState.Closed)
            {
                throw new InvalidOperationException();
            }

            Close();

            Dictionary<string, string> opts = ParseConnectionString(_connectionString);

            if (Convert.ToInt32(FindKey(opts, "Version", "3"), CultureInfo.InvariantCulture) != 3)
            {
                throw new NotSupportedException("Only SQLite Version 3 is supported at this time");
            }

            string fileName = FindKey(opts, "Data Source", "");
            if (String.IsNullOrEmpty(fileName))
            {
                fileName = FindKey(opts, "Uri", "");
                if (String.IsNullOrEmpty(fileName))
                {
                    throw new ArgumentException("Data Source cannot be empty.  Use :memory: to open an in-memory database");
                }

                fileName = MapUriPath(fileName);
            }
            if (String.Compare(fileName, ":MEMORY:", StringComparison.OrdinalIgnoreCase) == 0)
            {
                fileName = ":memory:";
            }
            else
            {
                fileName = this.ExpandFileName(fileName);
            }

            try
            {
                bool usePooling = SqliteConvert.ToBoolean(FindKey(opts, "Pooling", Boolean.FalseString));
                bool bUTF16 = SqliteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", Boolean.FalseString));
                int maxPoolSize = Convert.ToInt32(FindKey(opts, "Max Pool Size", "100"));

                _defaultTimeout = Convert.ToInt32(FindKey(opts, "Default Timeout", "30"), CultureInfo.CurrentCulture);

                _defaultIsolation =
                    (IsolationLevel)
                    Enum.Parse(typeof (IsolationLevel), FindKey(opts, "Default IsolationLevel", "Serializable"), true);
                if (_defaultIsolation != IsolationLevel.Serializable &&
                    _defaultIsolation != IsolationLevel.ReadCommitted)
                {
                    throw new NotSupportedException("Invalid Default IsolationLevel specified");
                }

                var dateFormat =
                    (SQLiteDateFormats)
                    Enum.Parse(typeof(SQLiteDateFormats), FindKey(opts, "DateTimeFormat", "ISO8601"), true);
                //string temp = FindKey(opts, "DateTimeFormat", "ISO8601");
                //if (String.Compare(temp, "ticks", true, CultureInfo.InvariantCulture) == 0) dateFormat = SQLiteDateFormats.Ticks;
                //else if (String.Compare(temp, "julianday", true, CultureInfo.InvariantCulture) == 0) dateFormat = SQLiteDateFormats.JulianDay;

                // SQLite automatically sets the encoding of the database to UTF16 if called from sqlite3_open16()
                this._sql = bUTF16 ? new SQLite3_UTF16(dateFormat) : new SQLite3(dateFormat);

                SQLiteOpenFlagsEnum flags = SQLiteOpenFlagsEnum.None;
                if (SqliteConvert.ToBoolean(FindKey(opts, "Read Only", Boolean.FalseString)))
                {
                    flags |= SQLiteOpenFlagsEnum.ReadOnly;
                }
                else
                {
                    flags |= SQLiteOpenFlagsEnum.ReadWrite;
                    if (SqliteConvert.ToBoolean(FindKey(opts, "FailIfMissing", Boolean.FalseString)) == false)
                    {
                        flags |= SQLiteOpenFlagsEnum.Create;
                    }
                }
                if (SqliteConvert.ToBoolean(FindKey(opts, "FileProtectionComplete", Boolean.FalseString)))
                {
                    flags |= SQLiteOpenFlagsEnum.FileProtectionComplete;
                }
                if (SqliteConvert.ToBoolean(FindKey(opts, "FileProtectionCompleteUnlessOpen", Boolean.FalseString)))
                {
                    flags |= SQLiteOpenFlagsEnum.FileProtectionCompleteUnlessOpen;
                }
                if (SqliteConvert.ToBoolean(FindKey(opts, "FileProtectionCompleteUntilFirstUserAuthentication", Boolean.FalseString)))
                {
                    flags |= SQLiteOpenFlagsEnum.FileProtectionCompleteUntilFirstUserAuthentication;
                }
                if (SqliteConvert.ToBoolean(FindKey(opts, "FileProtectionNone", Boolean.FalseString)))
                {
                    flags |= SQLiteOpenFlagsEnum.FileProtectionNone;
                }

                _sql.Open(fileName, flags, maxPoolSize, usePooling);

                _binaryGuid = SqliteConvert.ToBoolean(FindKey(opts, "BinaryGUID", Boolean.TrueString));

                string password = FindKey(opts, "Password", null);
                if (String.IsNullOrEmpty(password) == false)
                {
                    _sql.SetPassword(password);
                }
                else if (_password != null)
                {
                    _sql.SetPassword(_password);
                }
                _password = null;

                // TODO : _dataSource = Path.GetFileNameWithoutExtension(fileName);
                _dataSource = fileName;

                OnStateChange(ConnectionState.Open);
                _version++;

                using (SqliteCommand cmd = CreateCommand())
                {
                    string defValue;

                    if (fileName != ":memory:")
                    {
                        defValue = FindKey(opts, "Page Size", "1024");
                        if (Convert.ToInt32(defValue, CultureInfo.InvariantCulture) != 1024)
                        {
                            cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA page_size={0}",
                                                            defValue);
                            cmd.ExecuteNonQuery();
                        }
                    }

                    defValue = FindKey(opts, "Max Page Count", "0");
                    if (Convert.ToInt32(defValue, CultureInfo.InvariantCulture) != 0)
                    {
                        cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA max_page_count={0}",
                                                        defValue);
                        cmd.ExecuteNonQuery();
                    }

                    defValue = FindKey(opts, "Legacy Format", Boolean.FalseString);
                    cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA legacy_file_format={0}",
                                                    SqliteConvert.ToBoolean(defValue) ? "ON" : "OFF");
                    cmd.ExecuteNonQuery();

                    defValue = FindKey(opts, "Synchronous", "Normal");
                    if (String.Compare(defValue, "Full", StringComparison.OrdinalIgnoreCase) != 0)
                    {
                        cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA synchronous={0}", defValue);
                        cmd.ExecuteNonQuery();
                    }

                    defValue = FindKey(opts, "Cache Size", "2000");
                    if (Convert.ToInt32(defValue, CultureInfo.InvariantCulture) != 2000)
                    {
                        cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA cache_size={0}", defValue);
                        cmd.ExecuteNonQuery();
                    }

                    defValue = FindKey(opts, "Journal Mode", "Delete");
                    if (String.Compare(defValue, "Default", StringComparison.OrdinalIgnoreCase) != 0)
                    {
                        cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA journal_mode={0}",
                                                        defValue);
                        cmd.ExecuteNonQuery();
                    }
                }

                if (_commitHandler != null)
                {
                    _sql.SetCommitHook(_commitCallback);
                }

                if (_updateHandler != null)
                {
                    _sql.SetUpdateHook(_updateCallback);
                }

                if (_rollbackHandler != null)
                {
                    _sql.SetRollbackHook(_rollbackCallback);
                }

                if (global::System.Transactions.Transaction.Current != null && 
                    SqliteConvert.ToBoolean(FindKey(opts, "Enlist", Boolean.TrueString)))
                    EnlistTransaction(global::System.Transactions.Transaction.Current);
            }
            catch (SqliteException)
            {
                Close();

                throw;
            }
        }
        /// <summary>
        /// Opens the connection using the parameters found in the <see cref="ConnectionString">ConnectionString</see>
        /// </summary>
        public override void Open()
        {
            if (_connectionState != ConnectionState.Closed)
            {
                throw new InvalidOperationException();
            }

            Close();

            Dictionary <string, string> opts = ParseConnectionString(_connectionString);

            if (Convert.ToInt32(FindKey(opts, "Version", "3"), CultureInfo.InvariantCulture) != 3)
            {
                throw new NotSupportedException("Only SQLite Version 3 is supported at this time");
            }

            string fileName = FindKey(opts, "Data Source", "");

            if (String.IsNullOrEmpty(fileName))
            {
                fileName = FindKey(opts, "Uri", "");
                if (String.IsNullOrEmpty(fileName))
                {
                    throw new ArgumentException("Data Source cannot be empty.  Use :memory: to open an in-memory database");
                }

                fileName = MapUriPath(fileName);
            }
            if (String.Compare(fileName, ":MEMORY:", StringComparison.OrdinalIgnoreCase) == 0)
            {
                fileName = ":memory:";
            }
            else
            {
                fileName = this.ExpandFileName(fileName);
            }

            try
            {
                bool usePooling  = SqliteConvert.ToBoolean(FindKey(opts, "Pooling", Boolean.FalseString));
                bool bUTF16      = SqliteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", Boolean.FalseString));
                int  maxPoolSize = Convert.ToInt32(FindKey(opts, "Max Pool Size", "100"));

                _defaultTimeout = Convert.ToInt32(FindKey(opts, "Default Timeout", "30"), CultureInfo.CurrentCulture);

                _defaultIsolation =
                    (IsolationLevel)
                    Enum.Parse(typeof(IsolationLevel), FindKey(opts, "Default IsolationLevel", "Serializable"), true);
                if (_defaultIsolation != IsolationLevel.Serializable &&
                    _defaultIsolation != IsolationLevel.ReadCommitted)
                {
                    throw new NotSupportedException("Invalid Default IsolationLevel specified");
                }

                var dateFormat =
                    (SQLiteDateFormats)
                    Enum.Parse(typeof(SQLiteDateFormats), FindKey(opts, "DateTimeFormat", "ISO8601"), true);
                //string temp = FindKey(opts, "DateTimeFormat", "ISO8601");
                //if (String.Compare(temp, "ticks", true, CultureInfo.InvariantCulture) == 0) dateFormat = SQLiteDateFormats.Ticks;
                //else if (String.Compare(temp, "julianday", true, CultureInfo.InvariantCulture) == 0) dateFormat = SQLiteDateFormats.JulianDay;

                // SQLite automatically sets the encoding of the database to UTF16 if called from sqlite3_open16()
                this._sql = bUTF16 ? new SQLite3_UTF16(dateFormat) : new SQLite3(dateFormat);

                SQLiteOpenFlagsEnum flags = SQLiteOpenFlagsEnum.None;
                if (SqliteConvert.ToBoolean(FindKey(opts, "Read Only", Boolean.FalseString)))
                {
                    flags |= SQLiteOpenFlagsEnum.ReadOnly;
                }
                else
                {
                    flags |= SQLiteOpenFlagsEnum.ReadWrite;
                    if (SqliteConvert.ToBoolean(FindKey(opts, "FailIfMissing", Boolean.FalseString)) == false)
                    {
                        flags |= SQLiteOpenFlagsEnum.Create;
                    }
                }
                if (SqliteConvert.ToBoolean(FindKey(opts, "FileProtectionComplete", Boolean.FalseString)))
                {
                    flags |= SQLiteOpenFlagsEnum.FileProtectionComplete;
                }
                if (SqliteConvert.ToBoolean(FindKey(opts, "FileProtectionCompleteUnlessOpen", Boolean.FalseString)))
                {
                    flags |= SQLiteOpenFlagsEnum.FileProtectionCompleteUnlessOpen;
                }
                if (SqliteConvert.ToBoolean(FindKey(opts, "FileProtectionCompleteUntilFirstUserAuthentication", Boolean.FalseString)))
                {
                    flags |= SQLiteOpenFlagsEnum.FileProtectionCompleteUntilFirstUserAuthentication;
                }
                if (SqliteConvert.ToBoolean(FindKey(opts, "FileProtectionNone", Boolean.FalseString)))
                {
                    flags |= SQLiteOpenFlagsEnum.FileProtectionNone;
                }

                _sql.Open(fileName, flags, maxPoolSize, usePooling);

                _binaryGuid = SqliteConvert.ToBoolean(FindKey(opts, "BinaryGUID", Boolean.TrueString));

                string password = FindKey(opts, "Password", null);
                if (String.IsNullOrEmpty(password) == false)
                {
                    _sql.SetPassword(password);
                }
                else if (_password != null)
                {
                    _sql.SetPassword(_password);
                }
                _password = null;

                // TODO : _dataSource = Path.GetFileNameWithoutExtension(fileName);
                _dataSource = fileName;

                OnStateChange(ConnectionState.Open);
                _version++;

                using (SqliteCommand cmd = CreateCommand())
                {
                    string defValue;

                    if (fileName != ":memory:")
                    {
                        defValue = FindKey(opts, "Page Size", "1024");
                        if (Convert.ToInt32(defValue, CultureInfo.InvariantCulture) != 1024)
                        {
                            cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA page_size={0}",
                                                            defValue);
                            cmd.ExecuteNonQuery();
                        }
                    }

                    defValue = FindKey(opts, "Max Page Count", "0");
                    if (Convert.ToInt32(defValue, CultureInfo.InvariantCulture) != 0)
                    {
                        cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA max_page_count={0}",
                                                        defValue);
                        cmd.ExecuteNonQuery();
                    }

                    defValue        = FindKey(opts, "Legacy Format", Boolean.FalseString);
                    cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA legacy_file_format={0}",
                                                    SqliteConvert.ToBoolean(defValue) ? "ON" : "OFF");
                    cmd.ExecuteNonQuery();

                    defValue = FindKey(opts, "Synchronous", "Normal");
                    if (String.Compare(defValue, "Full", StringComparison.OrdinalIgnoreCase) != 0)
                    {
                        cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA synchronous={0}", defValue);
                        cmd.ExecuteNonQuery();
                    }

                    defValue = FindKey(opts, "Cache Size", "2000");
                    if (Convert.ToInt32(defValue, CultureInfo.InvariantCulture) != 2000)
                    {
                        cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA cache_size={0}", defValue);
                        cmd.ExecuteNonQuery();
                    }

                    defValue = FindKey(opts, "Journal Mode", "Delete");
                    if (String.Compare(defValue, "Default", StringComparison.OrdinalIgnoreCase) != 0)
                    {
                        cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA journal_mode={0}",
                                                        defValue);
                        cmd.ExecuteNonQuery();
                    }
                }

                if (_commitHandler != null)
                {
                    _sql.SetCommitHook(_commitCallback);
                }

                if (_updateHandler != null)
                {
                    _sql.SetUpdateHook(_updateCallback);
                }

                if (_rollbackHandler != null)
                {
                    _sql.SetRollbackHook(_rollbackCallback);
                }

                if (global::System.Transactions.Transaction.Current != null &&
                    SqliteConvert.ToBoolean(FindKey(opts, "Enlist", Boolean.TrueString)))
                {
                    EnlistTransaction(global::System.Transactions.Transaction.Current);
                }
            }
            catch (SqliteException)
            {
                Close();

                throw;
            }
        }